├── .editorconfig ├── .gitattributes ├── .github └── workflows │ ├── publish.yaml │ └── tests.yaml ├── .gitignore ├── .vscode ├── extensions.json └── settings.json ├── LICENSE ├── README.md ├── examples ├── .gitignore ├── 1_hello_world │ ├── HelloWorld.dracoproj │ ├── expected.verified.txt │ └── main.draco ├── 2_fibonacci │ ├── Fibonacci.dracoproj │ ├── expected.verified.txt │ └── main.draco ├── 3_99bottles │ ├── 99Bottles.dracoproj │ ├── expected.verified.txt │ └── main.draco └── Directory.Build.props ├── external ├── dap-specification │ ├── LICENSE.txt │ └── metaModel.json └── lsp-specification │ ├── LICENSE.txt │ └── metaModel.json ├── resources └── PackageIcon.png ├── scripts ├── check_namespaces.ps1 ├── clean_repo.ps1 ├── count_todos.ps1 ├── install_debugadapter.ps1 ├── install_langserver.ps1 ├── install_repl.ps1 ├── install_toolchain.ps1 ├── install_vscext.ps1 └── run_examples.ps1 └── src ├── Directory.Build.props ├── Draco.Chr.Tests ├── DeduplicateTest.cs ├── Draco.Chr.Tests.csproj ├── FibonacciTest.cs └── GcdTest.cs ├── Draco.Chr ├── Constraints │ ├── Constraint.cs │ ├── ConstraintStore.cs │ ├── IConstraint.cs │ └── PropagationHistory.cs ├── Draco.Chr.csproj ├── Rules │ ├── Head.cs │ ├── HeadContains.cs │ ├── HeadListType.cs │ ├── Propagation.cs │ ├── Rule.cs │ ├── RuleFactory.cs │ ├── Simpagation.cs │ ├── Simplification.cs │ └── Var.cs ├── Solve │ ├── DefinitionOrderSolver.cs │ ├── ISolver.cs │ └── PrioritizingSolver.cs └── Tracing │ ├── BroadcastTracer.cs │ ├── ITracer.cs │ ├── NullTracer.cs │ ├── StreamTracer.cs │ └── TextTracer.cs ├── Draco.Compiler.Benchmarks ├── Draco.Compiler.Benchmarks.csproj ├── E2eBenchmarks.cs ├── FolderBenchmarkBase.cs ├── Program.cs ├── SourceCodeParameter.cs ├── SyntaxBenchmarks.cs └── inputs │ └── big_string_literal.draco ├── Draco.Compiler.Cli ├── Draco.Compiler.Cli.csproj └── Program.cs ├── Draco.Compiler.DevHost ├── Draco.Compiler.DevHost.csproj └── Program.cs ├── Draco.Compiler.Fuzzer ├── CompilerFuzzerWindow.cs ├── Draco.Compiler.Fuzzer.csproj ├── FuzzerFactory.cs ├── Program.cs ├── SyntaxTreeInputMinimizer.cs ├── SyntaxTreeInputMutator.cs └── inputs │ ├── empty_functions.draco │ ├── gol.draco │ ├── simple_list.draco │ ├── todo_list.draco │ └── variadic_args.draco ├── Draco.Compiler.Tasks ├── Draco.Compiler.Tasks.csproj └── DracoCompiler.cs ├── Draco.Compiler.Tests ├── Draco.Compiler.Tests.csproj ├── EndToEnd │ ├── BclUsageTests.cs │ ├── CompilingCodeTests.cs │ ├── DoesNotCrashTests.cs │ └── MetadataTests.cs ├── NoParallelizationCollectionDefinition.cs ├── Scripting │ ├── IsCompleteEntryTests.cs │ ├── ReplSessionTests.cs │ └── ScriptTests.cs ├── Semantics │ ├── AttributeTests.cs │ ├── ControlFlowGraphTests.cs │ ├── ControlFlowGraphs │ │ ├── ControlFlowGraphTests.ChainedComparison.verified.txt │ │ ├── ControlFlowGraphTests.ConditionalGotoInAssignment.verified.txt │ │ ├── ControlFlowGraphTests.EarlyReturn.verified.txt │ │ ├── ControlFlowGraphTests.EmptyMethod.verified.txt │ │ ├── ControlFlowGraphTests.ForLoop.verified.txt │ │ ├── ControlFlowGraphTests.IfElse.verified.txt │ │ ├── ControlFlowGraphTests.UnconditionalBackwardsJump.verified.txt │ │ └── ControlFlowGraphTests.WhileLoop.verified.txt │ ├── DefiniteAssignmentTests.cs │ ├── DocumentationCommentsTests.cs │ ├── LocalFunctionsTests.cs │ ├── OverloadingTests.cs │ ├── ReturnsOnAllPathsTests.cs │ ├── SemanticModelTests.cs │ ├── SingleAssignmentTests.cs │ ├── SymbolResolutionTests.cs │ ├── TypeCheckingTests.cs │ └── VisibilityTests.cs ├── Services │ ├── CodeCompletionTests.cs │ └── SignatureHelpTests.cs ├── Syntax │ ├── FuzzerTestCases │ │ ├── crash-16a56ef2ee1f6a2fcc8ddf2911e0f3fb1b36e3b9.draco │ │ ├── crash-81bbb6ad94b3f4802afcaab9ef895fc0ddef70d4.draco │ │ └── timeout-0faaf5cf37107e7f0ff88777816a4b98f5fc3c63.draco │ ├── LexerTests.cs │ ├── ParseTreeFormatterTests.cs │ ├── ParserTests.cs │ ├── PositionTests.cs │ └── SyntaxHighlighterTests.cs ├── Tasks │ └── SolverTaskTests.cs ├── TestUtilities.cs └── Utilities │ └── RingBufferTests.cs ├── Draco.Compiler.Toolset ├── Draco.Compiler.Toolset.csproj ├── build │ ├── Draco.Compiler.Toolset.props │ └── Draco.Compiler.Toolset.targets └── buildMultiTargeting │ └── Draco.Compiler.Toolset.props ├── Draco.Compiler ├── Api │ ├── Compilation.cs │ ├── CompilationFlags.cs │ ├── Diagnostics │ │ ├── Diagnostic.cs │ │ ├── DiagnosticInfo.cs │ │ ├── DiagnosticRelatedInformation.cs │ │ ├── DiagnosticSeverity.cs │ │ ├── DiagnosticTemplate.cs │ │ ├── Diagnostic_Builder.cs │ │ ├── Location.cs │ │ ├── NullLocation.cs │ │ ├── RelativeLocation.cs │ │ └── SourceLocation.cs │ ├── GlobalImports.cs │ ├── MetadataReference.cs │ ├── Scripting │ │ ├── ExecutionResult.cs │ │ ├── ReplSession.cs │ │ └── Script.cs │ ├── Semantics │ │ ├── SemanticModel.cs │ │ ├── Symbol.cs │ │ ├── SymbolKind.cs │ │ └── Visibility.cs │ ├── Services │ │ ├── CodeCompletion │ │ │ ├── CompletionContext.cs │ │ │ ├── CompletionFilter.cs │ │ │ ├── CompletionItem.cs │ │ │ ├── CompletionKind.cs │ │ │ ├── CompletionService.cs │ │ │ └── Providers │ │ │ │ ├── CompletionProvider.cs │ │ │ │ ├── ExpressionCompletionProvider.cs │ │ │ │ ├── KeywordCompletionProvider.cs │ │ │ │ └── MemberCompletionProvider.cs │ │ ├── CodeFixes │ │ │ ├── CodeFix.cs │ │ │ ├── CodeFixProvider.cs │ │ │ ├── CodeFixService.cs │ │ │ └── ImportCodeFixProvider.cs │ │ └── Signature │ │ │ ├── SignatureItem.cs │ │ │ └── SignatureService.cs │ └── Syntax │ │ ├── Extensions │ │ ├── SyntaxNodeTraversalExtensions.cs │ │ └── SyntaxTreeRewriteExtensions.cs │ │ ├── HighlightFragment.cs │ │ ├── SeparatedSyntaxList.cs │ │ ├── SourceSpan.cs │ │ ├── SourceText.cs │ │ ├── SyntaxColoring.cs │ │ ├── SyntaxFactory.cs │ │ ├── SyntaxFacts.cs │ │ ├── SyntaxHighlighter.cs │ │ ├── SyntaxList.cs │ │ ├── SyntaxNode.cs │ │ ├── SyntaxPosition.cs │ │ ├── SyntaxRange.cs │ │ ├── SyntaxToken.cs │ │ ├── SyntaxTree.cs │ │ ├── SyntaxTrivia.cs │ │ ├── SyntaxVisitor.cs │ │ ├── TextEdit.cs │ │ └── TriviaKind.cs ├── Draco.Compiler.csproj └── Internal │ ├── Binding │ ├── Binder.cs │ ├── BinderCache.cs │ ├── BinderFacts.cs │ ├── Binder_Common.cs │ ├── Binder_Expression.cs │ ├── Binder_Label.cs │ ├── Binder_Lookup.cs │ ├── Binder_Lvalue.cs │ ├── Binder_Statement.cs │ ├── Binder_Symbol.cs │ ├── Binder_Type.cs │ ├── ForLoopBinder.cs │ ├── FunctionBinder.cs │ ├── GlobalBinding.cs │ ├── GlobalImportsBinder.cs │ ├── IBinderProvider.cs │ ├── ImportBinder.cs │ ├── ImportItem.cs │ ├── IncrementalBinder.cs │ ├── IntrinsicsBinder.cs │ ├── LocalBinder.cs │ ├── LookupFlags.cs │ ├── LookupResult.cs │ ├── LoopBinder.cs │ ├── ModuleBinder.cs │ ├── ScriptBinding.cs │ ├── ScriptModuleBinder.cs │ ├── SymbolResolutionErrors.cs │ ├── Tasks │ │ ├── BindingTask.cs │ │ ├── BindingTaskAwaiter.cs │ │ ├── BindingTaskCompletionSource.cs │ │ └── BindingTaskMethodBuilder.cs │ └── TypeCheckingErrors.cs │ ├── BoundTree │ ├── BoundNode.cs │ ├── BoundNodes.xml │ ├── BoundTreeCollector.cs │ ├── BoundTreeFactory.cs │ ├── BoundTreeRewriter.cs │ └── BoundTreeVisitor.cs │ ├── Codegen │ ├── AllocatedLocal.cs │ ├── CilCodegen.cs │ ├── CodegenErrors.cs │ ├── CodegenFlags.cs │ ├── MetadataCodegen.cs │ ├── MetadataWriter.cs │ ├── PdbCodegen.cs │ └── SequencePoint.cs │ ├── CompilerConstants.cs │ ├── Declarations │ ├── Declaration.cs │ ├── DeclarationTable.cs │ ├── FunctionDeclaration.cs │ ├── GlobalDeclaration.cs │ ├── MergedModuleDeclaration.cs │ └── SingleModuleDeclaration.cs │ ├── Diagnostics │ ├── ConcurrentDiagnosticBag.cs │ ├── DiagnosticBag.cs │ ├── DiagnosticCategory.cs │ ├── EmptyDiagnosticBag.cs │ └── SyntaxDiagnosticInfo.cs │ ├── Documentation │ ├── DocumentationElement.cs │ ├── DocumentationSection.cs │ ├── Extractors │ │ ├── MarkdownDocumentationExtractor.cs │ │ └── XmlDocumentationExtractor.cs │ └── SymbolDocumentation.cs │ ├── Evaluation │ ├── CompileTimeExecutor.cs │ ├── ConstantEvaluator.cs │ └── EvaluationErrors.cs │ ├── FlowAnalysis │ ├── BasicBlock.cs │ ├── CompleteFlowAnalysis.cs │ ├── ControlFlowGraph.cs │ ├── ControlFlowGraphBuilder.cs │ ├── ControlFlowGraphToDot.cs │ ├── DataFlowAnalysis.cs │ ├── Domains │ │ ├── DefiniteAssignmentDomain.cs │ │ ├── ReturnsOnAllPathsDomain.cs │ │ ├── SingleAssignmentDomain.cs │ │ └── TupleDomain.cs │ ├── FlowAnalysisErrors.cs │ ├── FlowCondition.cs │ └── FlowDomain.cs │ ├── Lowering │ ├── ClosureRewriter.cs │ ├── LocalRewriter.cs │ └── SequencePointInjector.cs │ ├── OptimizingIr │ ├── Codegen │ │ ├── AssemblyCodegen.cs │ │ ├── LocalCodegen.cs │ │ ├── MinimalAssemblyCodegen.cs │ │ ├── MinimalModuleSymbol.cs │ │ └── ModuleCodegen.cs │ ├── InstructionFactory.cs │ ├── Instructions │ │ ├── AddressOfInstruction.cs │ │ ├── ArithmeticInstruction.cs │ │ ├── ArithmeticOp.cs │ │ ├── ArrayLengthInstruction.cs │ │ ├── BoxInstruction.cs │ │ ├── BranchInstruction.cs │ │ ├── CallInstruction.cs │ │ ├── EndScope.cs │ │ ├── IInstruction.cs │ │ ├── IValueInstruction.cs │ │ ├── InstructionBase.cs │ │ ├── JumpInstruction.cs │ │ ├── LoadElementInstruction.cs │ │ ├── LoadFieldInstruction.cs │ │ ├── LoadInstruction.cs │ │ ├── NewArrayInstruction.cs │ │ ├── NewDelegateInstruction.cs │ │ ├── NewObjectInstruction.cs │ │ ├── NopInstruction.cs │ │ ├── RetInstruction.cs │ │ ├── SequencePoint.cs │ │ ├── StartScope.cs │ │ ├── StoreElementInstruction.cs │ │ ├── StoreFieldInstruction.cs │ │ ├── StoreInstruction.cs │ │ └── TreeInstruction.cs │ ├── Model │ │ ├── Assembly.cs │ │ ├── BasicBlock.cs │ │ ├── Constant.cs │ │ ├── DefaultValue.cs │ │ ├── IAssembly.cs │ │ ├── IBasicBlock.cs │ │ ├── IModule.cs │ │ ├── IOperand.cs │ │ ├── IProcedure.cs │ │ ├── ModelExtensions.cs │ │ ├── Module.cs │ │ ├── Procedure.cs │ │ ├── Register.cs │ │ └── Void.cs │ ├── OptimizationPipeline.cs │ ├── PassFactory.cs │ ├── Passes │ │ ├── DeadBlockElimination.cs │ │ ├── IPass.cs │ │ └── JumpThreading.cs │ └── Stackifier.cs │ ├── Scripting │ └── ReplContext.cs │ ├── Solver │ ├── ConstraintGraphTracer.cs │ ├── ConstraintLocator.cs │ ├── ConstraintSolver.cs │ ├── ConstraintSolver_Constraints.cs │ ├── ConstraintSolver_Operations.cs │ ├── ConstraintSolver_Rules.cs │ ├── ConstraintSolver_Utils.cs │ ├── Constraints │ │ ├── Assignable.cs │ │ ├── Callable.cs │ │ ├── CommonAncestor.cs │ │ ├── Constraint.cs │ │ ├── Indexer.cs │ │ ├── Member.cs │ │ ├── Overload.cs │ │ └── Same.cs │ ├── OverloadResolution │ │ ├── Argument.cs │ │ ├── ArgumentScore.cs │ │ ├── CallCandidate.cs │ │ ├── CallScore.cs │ │ ├── CallScoreComparison.cs │ │ ├── CallUtilities.cs │ │ └── OverloadCandidateSet.cs │ └── Tasks │ │ ├── SolverTask.cs │ │ ├── SolverTaskAwaiter.cs │ │ ├── SolverTaskCompletionSource.cs │ │ └── SolverTaskMethodBuilder.cs │ ├── SplitPath.cs │ ├── Symbols │ ├── AliasSymbol.cs │ ├── AttributeInstance.cs │ ├── ConstantValue.cs │ ├── Error │ │ ├── ErrorFunctionSymbol.cs │ │ ├── ErrorIndexerPropertySymbol.cs │ │ ├── ErrorLabelSymbol.cs │ │ ├── ErrorMemberSymbol.cs │ │ ├── ErrorPropertyAccessorSymbol.cs │ │ ├── ErrorPropertySymbol.cs │ │ ├── ErrorTypeSymbol.cs │ │ └── ErrorValueSymbol.cs │ ├── FieldSymbol.cs │ ├── FunctionSymbol.cs │ ├── FunctionTypeSymbol.cs │ ├── Generic │ │ ├── FieldInstanceSymbol.cs │ │ ├── FunctionInstanceSymbol.cs │ │ ├── GenericContext.cs │ │ ├── IGenericInstanceSymbol.cs │ │ ├── ParameterInstanceSymbol.cs │ │ ├── PropertyAccessorInstanceSymbol.cs │ │ ├── PropertyInstanceSymbol.cs │ │ └── TypeInstanceSymbol.cs │ ├── IMemberSymbol.cs │ ├── IOverridableSymbol.cs │ ├── IPropertyAccessorSymbol.cs │ ├── ITypedSymbol.cs │ ├── LabelSymbol.cs │ ├── LocalSymbol.cs │ ├── MergedModuleSymbol.cs │ ├── Metadata │ │ ├── AssemblyNameComparer.cs │ │ ├── IMetadataSymbol.cs │ │ ├── MetadataAssemblySymbol.cs │ │ ├── MetadataDocumentation.cs │ │ ├── MetadataFieldSymbol.cs │ │ ├── MetadataFunctionSignatureSymbol.cs │ │ ├── MetadataMethodSymbol.cs │ │ ├── MetadataNamespaceSymbol.cs │ │ ├── MetadataParameterSymbol.cs │ │ ├── MetadataPropertyAccessorSymbol.cs │ │ ├── MetadataPropertySymbol.cs │ │ ├── MetadataStaticClassSymbol.cs │ │ ├── MetadataSymbol.cs │ │ ├── MetadataTypeParameterSymbol.cs │ │ ├── MetadataTypeSymbol.cs │ │ ├── RawTypeProvider.cs │ │ └── TypeProvider.cs │ ├── ModuleSymbol.cs │ ├── ParameterSymbol.cs │ ├── PropertySymbol.cs │ ├── ReferenceTypeSymbol.cs │ ├── Script │ │ ├── ScriptAutoPropertySymbol.cs │ │ ├── ScriptEvalFunctionSymbol.cs │ │ ├── ScriptFieldSymbol.cs │ │ ├── ScriptFunctionSymbol.cs │ │ └── ScriptModuleSymbol.cs │ ├── Source │ │ ├── ISourceSymbol.cs │ │ ├── SourceAutoPropertySymbol.cs │ │ ├── SourceFieldSymbol.cs │ │ ├── SourceFunctionSymbol.cs │ │ ├── SourceLabelSymbol.cs │ │ ├── SourceLocalSymbol.cs │ │ ├── SourceModuleSymbol.cs │ │ ├── SourceParameterSymbol.cs │ │ └── SourceTypeParameterSymbol.cs │ ├── Symbol.cs │ ├── SymbolCollectionBuilder.cs │ ├── SymbolEqualityComparer.cs │ ├── SymbolExtensions.cs │ ├── SymbolVisitor.cs │ ├── Syntax │ │ ├── SyntaxAutoPropertySymbol.cs │ │ ├── SyntaxFieldSymbol.cs │ │ └── SyntaxFunctionSymbol.cs │ ├── Synthetized │ │ ├── Array │ │ │ ├── ArrayConstructorSymbol.cs │ │ │ ├── ArrayIndexPropertySymbol.cs │ │ │ └── ArrayTypeSymbol.cs │ │ ├── AutoProperty │ │ │ ├── AutoPropertyBackingFieldSymbol.cs │ │ │ ├── AutoPropertyGetterSymbol.cs │ │ │ └── AutoPropertySetterSymbol.cs │ │ ├── ConstructorFunctionSymbol.cs │ │ ├── DefaultValueFunctionSymbol.cs │ │ ├── DelegateIrFunctionSymbol.cs │ │ ├── FunctionGroupSymbol.cs │ │ ├── IntrinsicFunctionSymbol.cs │ │ ├── NeverTypeSymbol.cs │ │ ├── PrimitiveTypeSymbol.cs │ │ ├── SynthetizedAliasSymbol.cs │ │ ├── SynthetizedLabelSymbol.cs │ │ ├── SynthetizedLocalSymbol.cs │ │ ├── SynthetizedParameterSymbol.cs │ │ └── SynthetizedTypeParameterSymbol.cs │ ├── TypeParameterSymbol.cs │ ├── TypeSymbol.cs │ ├── TypeVariable.cs │ ├── VariableSymbol.cs │ ├── WellKnownTypes.cs │ └── WellKnownTypes.xml │ ├── Syntax │ ├── Formatting │ │ ├── Formatter.cs │ │ └── FormatterSettings.cs │ ├── Lexer.cs │ ├── Parser.cs │ ├── Rewriting │ │ ├── InsertRewriter.cs │ │ ├── RemoveRewriter.cs │ │ └── SyntaxRewriter.cs │ ├── SeparatedSyntaxList.Builder.cs │ ├── SeparatedSyntaxList.cs │ ├── SourceReader.cs │ ├── SourceText.cs │ ├── Syntax.xml │ ├── SyntaxDiagnosticTable.cs │ ├── SyntaxErrors.cs │ ├── SyntaxList.Builder.cs │ ├── SyntaxList.cs │ ├── SyntaxNode.cs │ ├── SyntaxToken.Builder.cs │ ├── SyntaxToken.cs │ ├── SyntaxTrivia.cs │ ├── SyntaxVisitor.cs │ └── TokenSource.cs │ └── Utilities │ ├── DotGraphBuilder.cs │ ├── GraphTraversal.cs │ ├── InterlockedUtils.cs │ ├── RingBuffer.cs │ └── StringUtils.cs ├── Draco.Coverage.Cli ├── Draco.Coverage.Cli.csproj └── Program.cs ├── Draco.Coverage.Tasks ├── CoverageWeaveTask.cs └── Draco.Coverage.Tasks.csproj ├── Draco.Coverage.Toolset ├── Draco.Coverage.Toolset.csproj └── build │ ├── Draco.Coverage.Toolset.props │ └── Draco.Coverage.Toolset.targets ├── Draco.Coverage ├── CoverageCollector.cs ├── CoverageResult.cs ├── Draco.Coverage.csproj ├── InstrumentationWeaver.cs ├── InstrumentationWeaverSettings.cs ├── InstrumentedAssembly.cs ├── Platform │ ├── BufferHandle.cs │ ├── IPlatformMethods.cs │ ├── PlatformUtils.cs │ ├── UnixPlatformMethods.cs │ └── Win32PlatformMethods.cs ├── SequencePoint.cs └── SharedMemory.cs ├── Draco.Dap ├── Adapter │ ├── Capabilities │ │ ├── IConfigurationSequence.cs │ │ └── IExceptionBreakpoint.cs │ ├── DebugAdapter.cs │ ├── DebugAdapterConnection.cs │ ├── DebugAdapterLifecycle.cs │ ├── DebugAdapterMethodHandler.cs │ ├── DebugClientProxy.cs │ ├── IDebugAdapter.cs │ ├── IDebugAdapterLifecycle.cs │ └── IDebugClient.cs ├── Attributes │ ├── CapabilityAttribute.cs │ ├── EventAttribute.cs │ └── RequestAttribute.cs ├── Draco.Dap.csproj ├── Model │ ├── AttachRequestArguments.cs │ ├── DapModel.xml │ ├── EventMessage.cs │ ├── LaunchRequestArguments.cs │ ├── ModelExtensions.cs │ ├── OneOf.xml │ ├── RequestMessage.cs │ └── ResponseMessage.cs └── Serialization │ ├── EnumValueConverter.cs │ └── OneOfConverter.cs ├── Draco.DebugAdapter ├── Capabilities │ └── ConfigurationSequence.cs ├── Draco.DebugAdapter.csproj ├── DracoDebugAdapter.cs ├── PathEqualityComparer.cs ├── Program.cs └── Translator.cs ├── Draco.Debugger.Tests ├── DebuggerTests.cs ├── Draco.Debugger.Tests.csproj ├── IoUtilsTests.cs └── TestDebugSession.cs ├── Draco.Debugger.Tui ├── DebuggerWindow.cs ├── Draco.Debugger.Tui.csproj ├── Program.cs ├── SourceFileListDataSource.cs └── SourceTextView.cs ├── Draco.Debugger ├── Breakpoints │ ├── Breakpoint.cs │ ├── EntryPointBreakpoint.cs │ └── MethodBreakpoint.cs ├── Debugger.cs ├── DebuggerEventHandlers.cs ├── DebuggerEvents.cs ├── DebuggerHost.cs ├── Draco.Debugger.csproj ├── Events │ ├── OnBreakpointEventArgs.cs │ ├── OnModuleEventArgs.cs │ └── OnStepEventArgs.cs ├── IO │ ├── IoHandles.cs │ ├── IoUtils.cs │ ├── IoWorker.cs │ └── RemoteIoHandles.cs ├── Method.cs ├── Module.cs ├── PeUtils.cs ├── Platform │ ├── IPlatformMethods.cs │ ├── PlatformUtils.cs │ ├── UnixPlatformMethods.cs │ └── Win32PlatformMethods.cs ├── RuntimeValues │ ├── ArrayValue.cs │ ├── ObjectValue.cs │ └── ValueUtils.cs ├── SequencePointExtensions.cs ├── SessionCache.cs ├── SourceFile.cs ├── SourcePosition.cs ├── SourceRange.cs ├── StackFrame.cs └── Thread.cs ├── Draco.Examples.Tests ├── Draco.Examples.Tests.csproj ├── ExamplesTests.cs ├── PriorityOrderer.cs ├── TestPriorityAttribute.cs └── TestUtils.cs ├── Draco.Extension.VsCode ├── .gitignore ├── .vscode │ ├── launch.json │ └── tasks.json ├── .vscodeignore ├── draco-language-configuration.json ├── msbuild-language-configuration.json ├── package-lock.json ├── package.json ├── resources │ ├── draco-project-icon-dark.svg │ ├── draco-project-icon-light.svg │ ├── draco-source-icon-dark.svg │ ├── draco-source-icon-light.svg │ └── extension-icon.png ├── src │ ├── assets.ts │ ├── commands.ts │ ├── debug_adapter.ts │ ├── extension.ts │ ├── language_server.ts │ ├── prompt.ts │ ├── result.ts │ ├── settings.ts │ ├── tools.ts │ └── user_flow.ts ├── syntaxes │ └── msbuild-draco.tmLanguage.json ├── tsconfig.json └── webpack.config.js ├── Draco.Fuzzing.Tui ├── Addons │ ├── CoverageScaleAddon.cs │ ├── CurrentInputAddon.cs │ ├── ExportFaultsAddon.cs │ ├── ExportFuzzTimesAddon.cs │ ├── ExportLcovAddon.cs │ ├── FaultListAddon.cs │ ├── FuzzerAddon.cs │ ├── IFuzzerAddon.cs │ ├── ImportInputAddon.cs │ ├── InputQueueAddon.cs │ ├── MinimizedInputAddon.cs │ ├── SeedFooterAddon.cs │ ├── StartStopAddon.cs │ └── TimingsAddon.cs ├── Draco.Fuzzing.Tui.csproj ├── FuzzerWindow.cs └── IFuzzerApplication.cs ├── Draco.Fuzzing ├── Components │ ├── ICoverageCompressor.cs │ ├── ICoverageReader.cs │ ├── IFaultDetector.cs │ ├── IInputCompressor.cs │ ├── IInputMinimizer.cs │ ├── IInputMutator.cs │ └── ITargetExecutor.cs ├── Draco.Fuzzing.csproj ├── FaultResult.cs ├── Fuzzer.cs ├── FuzzerSettings.cs ├── TargetInfo.cs ├── Tracing │ ├── BroadcastTracer.cs │ ├── EventTracer.cs │ ├── ITracer.cs │ ├── LockSyncTracer.cs │ ├── NullTracer.cs │ └── ObjectTracer.cs └── Utilities │ ├── ConcurrentHashSet.cs │ ├── ExceptionStackTraceEqualityComparer.cs │ ├── FaultEqualityComparer.cs │ └── SimdUtilities.cs ├── Draco.JsonRpc ├── Draco.JsonRpc.csproj ├── IJsonRpcClient.cs ├── IJsonRpcConnection.cs ├── IJsonRpcMethodHandler.cs ├── JsonRpcClientProxy.cs ├── JsonRpcConnection.cs └── JsonRpcMethodHandler.cs ├── Draco.LanguageServer ├── Capabilities │ ├── CodeAction.cs │ ├── CodeCompletion.cs │ ├── Configuration.cs │ ├── DidDeleteFiles.cs │ ├── FindReferences.cs │ ├── GotoDefinition.cs │ ├── Hover.cs │ ├── InlayHint.cs │ ├── PullDiagnostics.cs │ ├── Rename.cs │ ├── SignatureHelp.cs │ ├── TextDocumentFormatting.cs │ └── TextDocumentSync.cs ├── Configurations │ └── InlayHintsConfiguration.cs ├── Draco.LanguageServer.csproj ├── DracoConfigurationRepository.cs ├── DracoLanguageServer.cs ├── Program.cs └── Translator.cs ├── Draco.Lsp ├── Attributes │ ├── ClientCapabilityAttribute.cs │ ├── NotificationAttribute.cs │ ├── RegistrationOptionsAttribute.cs │ ├── RequestAttribute.cs │ └── ServerCapabilityAttribute.cs ├── Draco.Lsp.csproj ├── Model │ ├── DocumentUri.cs │ ├── FileDelete.cs │ ├── LspModel.xml │ ├── NotificationMessage.cs │ ├── OneOf.xml │ ├── RequestMessage.cs │ ├── ResponseError.cs │ └── ResponseMessage.cs ├── Serialization │ ├── DocumentUriConverter.cs │ ├── EnumValueConverter.cs │ ├── ModelInterfaceConverter.cs │ ├── OneOfConverter.cs │ ├── TupleConverter.cs │ └── UriConverter.cs └── Server │ ├── ILanguageClient.cs │ ├── ILanguageServer.cs │ ├── ILanguageServerLifecycle.cs │ ├── Language │ ├── ICodeAction.cs │ ├── ICodeCompletion.cs │ ├── IDiagnostics.cs │ ├── IFindReferences.cs │ ├── IGotoDefinition.cs │ ├── IHover.cs │ ├── IInlayHint.cs │ ├── IRename.cs │ ├── ISignatureHelp.cs │ └── ITextDocumentFormatting.cs │ ├── LanguageClientExtensions.cs │ ├── LanguageClientProxy.cs │ ├── LanguageServer.cs │ ├── LanguageServerConnection.cs │ ├── LanguageServerLifecycle.cs │ ├── LanguageServerMethodHandler.cs │ ├── TextDocument │ ├── ITextDocumentDidChange.cs │ ├── ITextDocumentDidClose.cs │ ├── ITextDocumentDidOpen.cs │ └── ITextDocumentSync.cs │ └── Workspace │ ├── IDidChangeConfiguration.cs │ └── IDidDeleteFiles.cs ├── Draco.ProjectSystem ├── BuildResult.cs ├── DesignTimeBuild.cs ├── Draco.ProjectSystem.csproj ├── Project.cs ├── StringWriterLogger.cs ├── Unit.cs └── Workspace.cs ├── Draco.ProjectTemplates ├── Draco.ProjectTemplates.msbuildproj ├── README.md └── templates │ └── console │ ├── .template.config │ └── template.json │ ├── DracoConsole.dracoproj │ └── main.draco ├── Draco.Repl ├── ColorScheme.cs ├── Configuration.cs ├── ConfigurationDefaults.cs ├── Draco.Repl.csproj ├── InterfaceColor.cs ├── Loop.cs ├── Program.cs └── ReplPromptCallbacks.cs ├── Draco.Sdk ├── Draco.Sdk.msbuildproj └── Sdk │ ├── Sdk.props │ └── Sdk.targets ├── Draco.SourceGeneration ├── BoundTree │ ├── BoundNodes.xsd │ ├── BoundTreeSourceGenerator.cs │ ├── DomainModel.cs │ ├── Template.cs │ └── XmlModel.cs ├── Dap │ ├── CsModel │ │ ├── Class.cs │ │ ├── Declaration.cs │ │ ├── Enum.cs │ │ ├── EnumMember.cs │ │ ├── Model.cs │ │ ├── Property.cs │ │ └── Type.cs │ ├── DapModel.xsd │ ├── DomainConfig.cs │ ├── Template.cs │ ├── Translator.cs │ ├── XmlConfig.cs │ └── XmlDapModelSourceGenerator.cs ├── Draco.SourceGeneration.csproj ├── EmbeddedResourceLoader.cs ├── EnumerableExtensions.cs ├── EquatableArray.cs ├── Lsp │ ├── CsModel │ │ ├── Class.cs │ │ ├── Declaration.cs │ │ ├── Enum.cs │ │ ├── EnumMember.cs │ │ ├── Interface.cs │ │ ├── Model.cs │ │ ├── Property.cs │ │ └── Type.cs │ ├── DomainConfig.cs │ ├── LspModel.xsd │ ├── Metamodel │ │ ├── AggregateType.cs │ │ ├── ArrayType.cs │ │ ├── Enumeration.cs │ │ ├── EnumerationEntry.cs │ │ ├── IDeclaration.cs │ │ ├── IDocumented.cs │ │ ├── LiteralType.cs │ │ ├── MapType.cs │ │ ├── MessageDirection.cs │ │ ├── MetaData.cs │ │ ├── MetaModel.cs │ │ ├── NamedType.cs │ │ ├── Notification.cs │ │ ├── Property.cs │ │ ├── Request.cs │ │ ├── Structure.cs │ │ ├── StructureLiteral.cs │ │ ├── StructureLiteralType.cs │ │ ├── Type.cs │ │ ├── TypeAlias.cs │ │ └── TypeConverter.cs │ ├── Template.cs │ ├── Translator.cs │ ├── XmlConfig.cs │ └── XmlLspModelSourceGenerator.cs ├── MappingEqualityComparer.cs ├── OneOf │ ├── DomainConfig.cs │ ├── OneOf.xsd │ ├── OneOfSourceGenerator.cs │ ├── Template.cs │ └── XmlConfig.cs ├── ReferenceEqualityComparer.cs ├── SyntaxTree │ ├── DomainModel.cs │ ├── Syntax.xsd │ ├── SyntaxTreeSourceGenerator.cs │ ├── Template.cs │ └── XmlModel.cs ├── TemplateUtils.cs ├── WellKnownTypes │ ├── DomainModel.cs │ ├── Template.cs │ ├── WellKnownTypes.xsd │ ├── WellKnownTypesSourceGenerator.cs │ └── XmlModel.cs └── XmlSourceGenerator.cs ├── Draco.SyntaxHighlighting ├── draco.tmLanguage.json └── draco.tmLanguage.yml └── Draco.sln /.gitattributes: -------------------------------------------------------------------------------- 1 | * text eol=lf 2 | *.png binary 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vs 2 | bin 3 | obj 4 | src/artifacts 5 | *.nupkg 6 | *.user 7 | **/Properties/launchSettings.json 8 | **/testenvironments.json 9 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "ms-dotnettools.csharp", 4 | "EditorConfig.EditorConfig" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.formatOnType": true, 3 | "omnisharp.enableRoslynAnalyzers": true, 4 | "omnisharp.enableEditorConfigSupport": true 5 | } 6 | -------------------------------------------------------------------------------- /examples/.gitignore: -------------------------------------------------------------------------------- 1 | Toolchain 2 | nuget.config 3 | -------------------------------------------------------------------------------- /examples/1_hello_world/HelloWorld.dracoproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Exe 4 | net8.0 5 | 6 | 7 | -------------------------------------------------------------------------------- /examples/1_hello_world/expected.verified.txt: -------------------------------------------------------------------------------- 1 | Hello, World! 2 | -------------------------------------------------------------------------------- /examples/1_hello_world/main.draco: -------------------------------------------------------------------------------- 1 | import System.Console; 2 | 3 | func main() { 4 | WriteLine("Hello, World!"); 5 | } 6 | -------------------------------------------------------------------------------- /examples/2_fibonacci/Fibonacci.dracoproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Exe 4 | net8.0 5 | 6 | 7 | -------------------------------------------------------------------------------- /examples/2_fibonacci/expected.verified.txt: -------------------------------------------------------------------------------- 1 | fib(0) = 1 2 | fib(1) = 1 3 | fib(2) = 2 4 | fib(3) = 3 5 | fib(4) = 5 6 | fib(5) = 8 7 | fib(6) = 13 8 | fib(7) = 21 9 | fib(8) = 34 10 | fib(9) = 55 11 | fib(10) = 89 12 | fib(11) = 144 13 | fib(12) = 233 14 | fib(13) = 377 15 | fib(14) = 610 16 | fib(15) = 987 17 | fib(16) = 1597 18 | fib(17) = 2584 19 | fib(18) = 4181 20 | fib(19) = 6765 21 | -------------------------------------------------------------------------------- /examples/2_fibonacci/main.draco: -------------------------------------------------------------------------------- 1 | import System.Console; 2 | import System.Linq.Enumerable; 3 | 4 | func main() { 5 | for (i in Range(0, 20)) { 6 | WriteLine("fib(\{i}) = \{fib(i)}"); 7 | } 8 | } 9 | 10 | func fib(n: int32): int32 = 11 | if (n < 2) 1 12 | else fib(n - 1) + fib(n - 2); 13 | -------------------------------------------------------------------------------- /examples/3_99bottles/99Bottles.dracoproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Exe 4 | net8.0 5 | 6 | 7 | -------------------------------------------------------------------------------- /examples/3_99bottles/main.draco: -------------------------------------------------------------------------------- 1 | import System.Console; 2 | import System.Linq.Enumerable; 3 | 4 | func main() { 5 | for (i in Reverse(Range(0, 100))) { 6 | WriteLine(""" 7 | \{capitalize(bottles(i))} of beer on the wall, 8 | \{bottles(i)} of beer. 9 | """); 10 | 11 | if (i > 0) { 12 | WriteLine(""" 13 | Take one down, pass it around, 14 | \{bottles(i - 1)} of beer on the wall. 15 | 16 | """); 17 | } else { 18 | WriteLine(""" 19 | Go to the store, buy some more, 20 | 99 bottles of beer on the wall. 21 | """); 22 | } 23 | } 24 | } 25 | 26 | func bottles(n: int32): string = 27 | if (n == 0) "no more bottles" 28 | else if (n == 1) "1 bottle" 29 | else "\{n} bottles"; 30 | 31 | func capitalize(s: string): string = 32 | "\{char.ToUpper(s[0])}\{s.Substring(1)}"; 33 | -------------------------------------------------------------------------------- /examples/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /external/dap-specification/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) Microsoft Corporation. 2 | 3 | All rights reserved. 4 | 5 | Distributed under the following terms: 6 | 7 | 1. Documentation is licensed under the Creative Commons Attribution 3.0 United States License. Code is licensed under the MIT License. 8 | 2. This license does not grant you rights to use any trademarks or logos of Microsoft. For Microsoft’s general trademark guidelines, go to http://go.microsoft.com/fwlink/?LinkID=254653 -------------------------------------------------------------------------------- /external/lsp-specification/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) Microsoft Corporation. 2 | 3 | All rights reserved. 4 | 5 | Distributed under the following terms: 6 | 7 | 1. Documentation is licensed under the Creative Commons Attribution 3.0 United States License. Code is licensed under the MIT License. 8 | 2. This license does not grant you rights to use any trademarks or logos of Microsoft. For Microsoft’s general trademark guidelines, go to http://go.microsoft.com/fwlink/?LinkID=254653 -------------------------------------------------------------------------------- /resources/PackageIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Draco-lang/Compiler/57787f7ecef1a100e3496ba433950c84fcaed602/resources/PackageIcon.png -------------------------------------------------------------------------------- /scripts/clean_repo.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Description 3 | Clean the repository by removing all untracked files and directories. 4 | #> 5 | 6 | git clean -xdf 7 | -------------------------------------------------------------------------------- /scripts/count_todos.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Description 3 | Counts the number of TODOs in the repository for each commit. 4 | #> 5 | 6 | git stash 7 | $commits = git rev-list --reverse HEAD 8 | foreach ($commit in $commits) { 9 | git checkout $commit >$null 2>&1 10 | $date = git show -s --format='%ci' $commit 11 | $todos = git ls-files .. | xargs grep -i todo | wc -l 12 | Write-Output "${commit};${date};${todos}" 13 | } 14 | git stash pop 15 | -------------------------------------------------------------------------------- /scripts/install_debugadapter.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Description 3 | Installs the Draco Debug Adapter tool globally from source. 4 | This helps testing debugger or debug adapter changes while development. 5 | #> 6 | 7 | $ErrorActionPreference = "Stop" 8 | Push-Location $PSScriptRoot 9 | 10 | dotnet pack ../src/Draco.DebugAdapter --configuration Debug --output . 11 | if ((dotnet tool list --global) -match "Draco.DebugAdapter") { 12 | dotnet tool uninstall --global Draco.DebugAdapter 13 | } 14 | dotnet tool install --global --add-source . Draco.DebugAdapter 15 | 16 | Pop-Location 17 | -------------------------------------------------------------------------------- /scripts/install_langserver.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Description 3 | Install the Draco Language Server tool globally from source. 4 | This helps testing language server changes while development. 5 | #> 6 | 7 | $ErrorActionPreference = "Stop" 8 | Push-Location $PSScriptRoot 9 | 10 | dotnet pack ../src/Draco.LanguageServer --configuration Debug --output . 11 | if ((dotnet tool list --global) -match "Draco.LanguageServer") { 12 | dotnet tool uninstall --global Draco.LanguageServer 13 | } 14 | dotnet tool install --global --add-source . Draco.LanguageServer 15 | 16 | Pop-Location 17 | -------------------------------------------------------------------------------- /scripts/install_repl.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Description 3 | Install the Draco Repl tool globally from source. 4 | This helps testing repl changes while development. 5 | #> 6 | 7 | $ErrorActionPreference = "Stop" 8 | Push-Location $PSScriptRoot 9 | 10 | dotnet pack ../src/Draco.Repl --configuration Debug --output . 11 | if ((dotnet tool list --global) -match "Draco.Repl") { 12 | dotnet tool uninstall --global Draco.Repl 13 | } 14 | dotnet tool install --global --add-source . Draco.Repl 15 | 16 | Pop-Location 17 | -------------------------------------------------------------------------------- /scripts/install_vscext.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Description 3 | Installs the Draco Visual Studio Code extension from source. 4 | This helps testing extension changes while development. 5 | #> 6 | 7 | $ErrorActionPreference = "Stop" 8 | Push-Location $PSScriptRoot 9 | 10 | cd ../src/Draco.Extension.VsCode 11 | npm i 12 | echo 'y' | vsce package 13 | $vsixFile = Get-ChildItem -Filter "*.vsix" | Select-Object -First 1 14 | code --install-extension $vsixFile --force 15 | 16 | Pop-Location 17 | -------------------------------------------------------------------------------- /scripts/run_examples.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Description 3 | Runs all examples in the examples directory. 4 | #> 5 | 6 | $ErrorActionPreference = "Stop" 7 | Push-Location $PSScriptRoot 8 | 9 | # Save location and go to the examples directory 10 | Set-Location "../examples" 11 | 12 | # Find each subdirectory with a .dracoproj file 13 | $directories = Get-ChildItem -Directory | Where-Object { $_.GetFiles("*.dracoproj").Count -gt 0 } 14 | 15 | # Run each example 16 | foreach ($directory in $directories) { 17 | # Save the current location and go to the example directory 18 | Push-Location 19 | Set-Location $directory.FullName 20 | 21 | # Log a message about the ran example 22 | Write-Host "Running example in $directory" 23 | 24 | # Run the example 25 | dotnet run 26 | 27 | # Restore the old location 28 | Pop-Location 29 | } 30 | 31 | Pop-Location 32 | -------------------------------------------------------------------------------- /src/Draco.Chr.Tests/DeduplicateTest.cs: -------------------------------------------------------------------------------- 1 | using Draco.Chr.Constraints; 2 | using Draco.Chr.Rules; 3 | using Draco.Chr.Solve; 4 | using static Draco.Chr.Rules.RuleFactory; 5 | 6 | namespace Draco.Chr.Tests; 7 | 8 | public sealed class DeduplicateTest 9 | { 10 | [Fact] 11 | public void Deduplicate() 12 | { 13 | var numbers = new[] { 1, 2, 3, 4, 3, 1, 2, 3, 1, 3 }; 14 | var expected = numbers.ToHashSet(); 15 | 16 | var solver = new DefinitionOrderSolver(ConstructRules()); 17 | var store = new ConstraintStore(); 18 | store.AddRange(numbers); 19 | 20 | solver.Solve(store); 21 | 22 | Assert.Equal(expected.Count, store.Count); 23 | Assert.True(expected.SetEquals(store.Select(c => c.Value).OfType())); 24 | } 25 | 26 | private static IEnumerable ConstructRules() 27 | { 28 | var X = new Var("X"); 29 | 30 | yield return Simpagation(X, Sep, X); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Draco.Chr/Draco.Chr.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/Draco.Chr/Rules/HeadContains.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.Chr.Rules; 2 | 3 | /// 4 | /// Signals what a head contains for matching information. 5 | /// 6 | internal enum HeadContains 7 | { 8 | /// 9 | /// Unspecified, can't optimize matching. 10 | /// 11 | Any, 12 | 13 | /// 14 | /// Type-level information, can filter based on constraint type. 15 | /// 16 | Type, 17 | 18 | /// 19 | /// Exact value, can filter based on constraint value. 20 | /// 21 | Value, 22 | } 23 | -------------------------------------------------------------------------------- /src/Draco.Chr/Rules/HeadListType.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.Chr.Rules; 2 | 3 | /// 4 | /// The way set of heads were specified to match. 5 | /// 6 | internal enum HeadListType 7 | { 8 | /// 9 | /// Only the number of heads was specified. 10 | /// 11 | SizeSpecified, 12 | 13 | /// 14 | /// The types of the heads were specified. 15 | /// 16 | TypesSpecified, 17 | 18 | /// 19 | /// The heads were specified individually. 20 | /// 21 | ComplexDefinition, 22 | } 23 | -------------------------------------------------------------------------------- /src/Draco.Chr/Rules/Var.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.Chr.Rules; 2 | 3 | /// 4 | /// A variable within a rule. 5 | /// 6 | public sealed class Var(string name) 7 | { 8 | /// 9 | /// The name of the variable. 10 | /// 11 | public string Name { get; } = name; 12 | 13 | public override string ToString() => this.Name; 14 | } 15 | -------------------------------------------------------------------------------- /src/Draco.Chr/Solve/DefinitionOrderSolver.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Draco.Chr.Rules; 5 | using Draco.Chr.Tracing; 6 | 7 | namespace Draco.Chr.Solve; 8 | 9 | /// 10 | /// A solver that prioritizes rules based on their definition order. 11 | /// 12 | public sealed class DefinitionOrderSolver( 13 | IEnumerable rules, 14 | IEqualityComparer? comparer = null, 15 | ITracer? tracer = null) : PrioritizingSolver(comparer, tracer) 16 | { 17 | public override IEnumerable Rules { get; } = rules.ToList(); 18 | } 19 | -------------------------------------------------------------------------------- /src/Draco.Chr/Solve/ISolver.cs: -------------------------------------------------------------------------------- 1 | using Draco.Chr.Constraints; 2 | 3 | namespace Draco.Chr.Solve; 4 | 5 | /// 6 | /// Represents a CHR solver. 7 | /// 8 | public interface ISolver 9 | { 10 | /// 11 | /// Solves the given store and returns the result. 12 | /// 13 | /// The initial constraint store. 14 | /// The solved constraint store. Can be the same mutated instance as . 15 | public ConstraintStore Solve(ConstraintStore store); 16 | } 17 | -------------------------------------------------------------------------------- /src/Draco.Chr/Tracing/NullTracer.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Draco.Chr.Constraints; 3 | using Draco.Chr.Rules; 4 | 5 | namespace Draco.Chr.Tracing; 6 | 7 | /// 8 | /// A tracer that discards all information. 9 | /// 10 | public sealed class NullTracer : ITracer 11 | { 12 | /// 13 | /// A singleton instance of the tracer. 14 | /// 15 | public static NullTracer Instance { get; } = new(); 16 | 17 | private NullTracer() 18 | { 19 | } 20 | 21 | public void BeforeMatch(Rule rule, IEnumerable constraints, ConstraintStore store) { } 22 | public void AfterMatch( 23 | Rule rule, 24 | IEnumerable matchedConstraints, 25 | IEnumerable newConstraints, 26 | ConstraintStore store) 27 | { 28 | } 29 | 30 | public void Start(ConstraintStore store) { } 31 | public void End(ConstraintStore store) { } 32 | public void Flush() { } 33 | } 34 | -------------------------------------------------------------------------------- /src/Draco.Compiler.Benchmarks/E2eBenchmarks.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Immutable; 2 | using System.IO; 3 | using System.Linq; 4 | using BenchmarkDotNet.Attributes; 5 | using Draco.Compiler.Api; 6 | using Draco.Compiler.Api.Syntax; 7 | 8 | namespace Draco.Compiler.Benchmarks; 9 | 10 | public class E2eBenchmarks() : FolderBenchmarkBase("inputs") 11 | { 12 | // 64 KB should be enough for anyone, right Bill? 13 | private readonly MemoryStream peStream = new(1024 * 64); 14 | 15 | [IterationSetup] 16 | public void Setup() => this.peStream.Position = 0; 17 | 18 | [Benchmark] 19 | public EmitResult Compile() 20 | { 21 | var syntaxTree = SyntaxTree.Parse(this.Input.Code, Path.GetFullPath(this.Input.Path)); 22 | var compilation = Compilation.Create( 23 | syntaxTrees: [syntaxTree], 24 | metadataReferences: Basic.Reference.Assemblies.Net80.ReferenceInfos.All 25 | .Select(r => MetadataReference.FromPeStream(new MemoryStream(r.ImageBytes))) 26 | .ToImmutableArray()); 27 | return compilation.Emit(peStream: this.peStream); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Draco.Compiler.Benchmarks/FolderBenchmarkBase.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.IO; 3 | using System.Linq; 4 | using BenchmarkDotNet.Attributes; 5 | 6 | namespace Draco.Compiler.Benchmarks; 7 | 8 | public abstract class FolderBenchmarkBase(string path) 9 | { 10 | [ParamsSource(nameof(GetSourcesFromFolder))] 11 | public SourceCodeParameter Input { get; set; } = null!; 12 | 13 | public IEnumerable GetSourcesFromFolder() => Directory 14 | .GetFiles(path) 15 | .Select(SourceCodeParameter.FromPath); 16 | } 17 | -------------------------------------------------------------------------------- /src/Draco.Compiler.Benchmarks/Program.cs: -------------------------------------------------------------------------------- 1 | using BenchmarkDotNet.Running; 2 | 3 | namespace Draco.Compiler.Benchmarks; 4 | 5 | internal class Program 6 | { 7 | internal static void Main(string[] args) => 8 | BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args); 9 | } 10 | -------------------------------------------------------------------------------- /src/Draco.Compiler.Benchmarks/SourceCodeParameter.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | 3 | namespace Draco.Compiler.Benchmarks; 4 | 5 | public sealed record class SourceCodeParameter(string Path, string Code) 6 | { 7 | public static SourceCodeParameter FromPath(string path) => new(path, File.ReadAllText(path)); 8 | 9 | public override string ToString() => System.IO.Path.GetFileName(this.Path); 10 | } 11 | -------------------------------------------------------------------------------- /src/Draco.Compiler.Cli/Draco.Compiler.Cli.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | false 6 | 7 | 9 | false 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/Draco.Compiler.DevHost/Draco.Compiler.DevHost.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/Draco.Compiler.Fuzzer/inputs/empty_functions.draco: -------------------------------------------------------------------------------- 1 | func main() {} 2 | func foo() {} 3 | func bar() {} 4 | func baz() {} 5 | func qux() {} 6 | -------------------------------------------------------------------------------- /src/Draco.Compiler.Fuzzer/inputs/simple_list.draco: -------------------------------------------------------------------------------- 1 | import System.Collections.Generic; 2 | import System.Linq.Enumerable; 3 | import System.Console; 4 | 5 | func main() { 6 | val l = List(); 7 | for (i in Range(0, 100)) { 8 | l.Add(i); 9 | } 10 | WriteLine("Count = \{l.Count}"); 11 | } 12 | -------------------------------------------------------------------------------- /src/Draco.Compiler.Fuzzer/inputs/variadic_args.draco: -------------------------------------------------------------------------------- 1 | import System.Console; 2 | 3 | func arrayOf(...vs: Array): Array = vs; 4 | 5 | func main() { 6 | for (s in arrayOf("abc", "def", "ghi")) { 7 | WriteLine(s); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/Draco.Compiler.Tasks/Draco.Compiler.Tasks.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | false 6 | disable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/Draco.Compiler.Tests/NoParallelizationCollectionDefinition.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.Compiler.Tests; 2 | 3 | [CollectionDefinition(nameof(NoParallelizationCollectionDefinition), DisableParallelization = true)] 4 | public static class NoParallelizationCollectionDefinition 5 | { 6 | } 7 | -------------------------------------------------------------------------------- /src/Draco.Compiler.Tests/Scripting/IsCompleteEntryTests.cs: -------------------------------------------------------------------------------- 1 | using Draco.Compiler.Api.Scripting; 2 | 3 | namespace Draco.Compiler.Tests.Scripting; 4 | 5 | public sealed class IsCompleteEntryTests 6 | { 7 | [InlineData("", true)] 8 | [InlineData("// hello comments", true)] 9 | [InlineData("1", true)] 10 | [InlineData("1 + 2", true)] 11 | [InlineData("1 + ", false)] 12 | [InlineData("foo()", true)] 13 | [InlineData("foo(", false)] 14 | [InlineData("var x = 0;", true)] 15 | [InlineData("x < y", true)] 16 | [InlineData("x < y < z", true)] 17 | [InlineData("func foo() {", false)] 18 | [InlineData(""" 19 | func foo() { 20 | } 21 | """, true)] 22 | [Theory] 23 | public void IsCompleteEntry(string input, bool expected) 24 | { 25 | var result = ReplSession.IsCompleteEntry(input); 26 | Assert.Equal(expected, result); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Draco.Compiler.Tests/Semantics/ControlFlowGraphs/ControlFlowGraphTests.ConditionalGotoInAssignment.verified.txt: -------------------------------------------------------------------------------- 1 | digraph ControlFlowGraph { 2 | 0 [shape=rectangle, label=< >, xlabel="b0"]; 3 | 1 [shape=rectangle, label=< >, xlabel="b1"]; 4 | 2 [shape=rectangle, label=< >, xlabel="b2"]; 5 | 3 [shape=rectangle, label=>, xlabel="b4"]; 6 | 4 [shape=rectangle, label=e3: ReturnExpression(Value = unit)
>, xlabel="b3"]; 7 | 0 -> 1 [label="WhenTrue(b)"]; 8 | 0 -> 2 [label="WhenFalse(b)"]; 9 | 2 -> 3 [label="Always"]; 10 | 3 -> 4 [label="Always"]; 11 | 1 -> 4 [label="Always"]; 12 | } -------------------------------------------------------------------------------- /src/Draco.Compiler.Tests/Semantics/ControlFlowGraphs/ControlFlowGraphTests.EarlyReturn.verified.txt: -------------------------------------------------------------------------------- 1 | digraph ControlFlowGraph { 2 | 0 [shape=rectangle, label=>, xlabel="b0"]; 3 | 1 [shape=rectangle, label=>, xlabel="b1"]; 4 | 2 [shape=rectangle, label=< >, xlabel="b2"]; 5 | 3 [shape=rectangle, label=e2: ReturnExpression(Value = unit)
>, xlabel="b4"]; 6 | 4 [shape=rectangle, label=< >, xlabel="b3"]; 7 | 0 -> 1 [label="WhenTrue(b)"]; 8 | 0 -> 2 [label="WhenFalse(b)"]; 9 | 2 -> 3 [label="Always"]; 10 | 3 -> 4 [label="Always"]; 11 | 1 -> 4 [label="Always"]; 12 | } -------------------------------------------------------------------------------- /src/Draco.Compiler.Tests/Semantics/ControlFlowGraphs/ControlFlowGraphTests.EmptyMethod.verified.txt: -------------------------------------------------------------------------------- 1 | digraph ControlFlowGraph { 2 | 0 [shape=rectangle, label=>, xlabel="b0"]; 3 | } -------------------------------------------------------------------------------- /src/Draco.Compiler.Tests/Semantics/ControlFlowGraphs/ControlFlowGraphTests.ForLoop.verified.txt: -------------------------------------------------------------------------------- 1 | digraph ControlFlowGraph { 2 | 0 [shape=rectangle, label=< >, xlabel="b0"]; 3 | 1 [shape=rectangle, label=< >, xlabel="b1"]; 4 | 2 [shape=rectangle, label=>, xlabel="b2"]; 5 | 3 [shape=rectangle, label=>, xlabel="b3"]; 6 | 0 -> 1 [label="Always"]; 7 | 1 -> 2 [label="SequenceItem(s)"]; 8 | 1 -> 3 [label="SequenceEnd(s)"]; 9 | 2 -> 1 [label="Always"]; 10 | } -------------------------------------------------------------------------------- /src/Draco.Compiler.Tests/Semantics/ControlFlowGraphs/ControlFlowGraphTests.IfElse.verified.txt: -------------------------------------------------------------------------------- 1 | digraph ControlFlowGraph { 2 | 0 [shape=rectangle, label=< >, xlabel="b0"]; 3 | 1 [shape=rectangle, label=>, xlabel="b1"]; 4 | 2 [shape=rectangle, label=>, xlabel="b2"]; 5 | 3 [shape=rectangle, label=>, xlabel="b3"]; 6 | 0 -> 1 [label="WhenTrue(b)"]; 7 | 0 -> 2 [label="WhenFalse(b)"]; 8 | 2 -> 3 [label="Always"]; 9 | 1 -> 3 [label="Always"]; 10 | } -------------------------------------------------------------------------------- /src/Draco.Compiler.Tests/Semantics/ControlFlowGraphs/ControlFlowGraphTests.UnconditionalBackwardsJump.verified.txt: -------------------------------------------------------------------------------- 1 | digraph ControlFlowGraph { 2 | 0 [shape=rectangle, label=< >, xlabel="b0"]; 3 | 1 [shape=rectangle, label=< >, xlabel="b1"]; 4 | 0 -> 1 [label="Always"]; 5 | 1 -> 1 [label="Always"]; 6 | } -------------------------------------------------------------------------------- /src/Draco.Compiler.Tests/Semantics/ControlFlowGraphs/ControlFlowGraphTests.WhileLoop.verified.txt: -------------------------------------------------------------------------------- 1 | digraph ControlFlowGraph { 2 | 0 [shape=rectangle, label=>, xlabel="b0"]; 3 | 1 [shape=rectangle, label=>, xlabel="b1"]; 4 | 2 [shape=rectangle, label=e3: AssignmentExpression(CompoundOperator = op_Addition, Left = i, Right = 1)
>, xlabel="b2"]; 5 | 3 [shape=rectangle, label=>, xlabel="b3"]; 6 | 0 -> 1 [label="Always"]; 7 | 1 -> 2 [label="WhenTrue(e1)"]; 8 | 1 -> 3 [label="WhenFalse(e1)"]; 9 | 2 -> 1 [label="Always"]; 10 | } -------------------------------------------------------------------------------- /src/Draco.Compiler.Tests/Syntax/FuzzerTestCases/crash-16a56ef2ee1f6a2fcc8ddf2911e0f3fb1b36e3b9.draco: -------------------------------------------------------------------------------- 1 | "\u{333333} -------------------------------------------------------------------------------- /src/Draco.Compiler.Tests/Syntax/FuzzerTestCases/crash-81bbb6ad94b3f4802afcaab9ef895fc0ddef70d4.draco: -------------------------------------------------------------------------------- 1 | '󉉉��������������������������������������� 2 | -------------------------------------------------------------------------------- /src/Draco.Compiler.Tests/Syntax/FuzzerTestCases/timeout-0faaf5cf37107e7f0ff88777816a4b98f5fc3c63.draco: -------------------------------------------------------------------------------- 1 | ߄ 2 | -------------------------------------------------------------------------------- /src/Draco.Compiler.Toolset/build/Draco.Compiler.Toolset.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | .draco 5 | Draco 6 | Managed 7 | 8 | 9 | false 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/Draco.Compiler.Toolset/buildMultiTargeting/Draco.Compiler.Toolset.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Api/CompilationFlags.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Draco.Compiler.Api; 4 | 5 | /// 6 | /// Special settings flags for the compiler. 7 | /// 8 | [Flags] 9 | public enum CompilationFlags 10 | { 11 | /// 12 | /// No special settings. 13 | /// 14 | None = 0, 15 | 16 | /// 17 | /// The compilation is in scripting mode. 18 | /// 19 | /// This generally means that it will only consume a single syntax tree with a single 20 | /// script entry syntax. 21 | /// 22 | ScriptingMode = 1 << 0, 23 | } 24 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Api/Diagnostics/DiagnosticSeverity.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.Compiler.Api.Diagnostics; 2 | 3 | /// 4 | /// The possible severities of diagnostic messages. 5 | /// 6 | public enum DiagnosticSeverity 7 | { 8 | /// 9 | /// Informational diagnostic message. 10 | /// 11 | Info, 12 | 13 | /// 14 | /// Warning diagnostic message. 15 | /// 16 | Warning, 17 | 18 | /// 19 | /// Error diagnostic message. 20 | /// 21 | Error, 22 | } 23 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Api/Diagnostics/NullLocation.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.Compiler.Api.Diagnostics; 2 | 3 | /// 4 | /// Represents no location. 5 | /// 6 | internal sealed class NullLocation : Location 7 | { 8 | public override bool IsNone => true; 9 | 10 | public override string ToString() => ""; 11 | } 12 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Api/Diagnostics/RelativeLocation.cs: -------------------------------------------------------------------------------- 1 | using Draco.Compiler.Api.Syntax; 2 | 3 | namespace Draco.Compiler.Api.Diagnostics; 4 | 5 | /// 6 | /// Represents a location relative to some syntax element. 7 | /// 8 | internal sealed class RelativeLocation(SyntaxNode relativeTo, Location originalLocation) : Location 9 | { 10 | public override SourceText SourceText => originalLocation.SourceText; 11 | public override SourceSpan? Span => originalLocation.Span?.RelativeTo(relativeTo.Span.Start); 12 | 13 | public override string ToString() 14 | { 15 | var range = this.Range; 16 | if (range is null) return originalLocation.ToString()!; 17 | 18 | var position = range.Value.Start; 19 | return $"at line {position.Line + 1}, character {position.Column + 1}"; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Api/Diagnostics/SourceLocation.cs: -------------------------------------------------------------------------------- 1 | using Draco.Compiler.Api.Syntax; 2 | 3 | namespace Draco.Compiler.Api.Diagnostics; 4 | 5 | /// 6 | /// Represents an in-source location. 7 | /// 8 | internal sealed class SourceLocation(SourceText sourceText, SourceSpan span) : Location 9 | { 10 | public override SourceText SourceText { get; } = sourceText; 11 | public override SourceSpan? Span => span; 12 | 13 | public SourceLocation(SyntaxTree syntaxTree, SourceSpan span) 14 | : this(syntaxTree.SourceText, span) 15 | { 16 | } 17 | 18 | public SourceLocation(SyntaxNode node) 19 | : this(node.Tree, node.Span) 20 | { 21 | } 22 | 23 | public override string ToString() 24 | { 25 | var position = this.Range!.Value.Start; 26 | return $"at line {position.Line + 1}, character {position.Column + 1}"; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Api/Semantics/SymbolKind.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.Compiler.Api.Semantics; 2 | 3 | /// 4 | /// The different kinds of symbols. 5 | /// 6 | public enum SymbolKind 7 | { 8 | Module, 9 | Field, 10 | Property, 11 | Local, 12 | Parameter, 13 | Function, 14 | FunctionGroup, 15 | Type, 16 | TypeParameter, 17 | Alias, 18 | Label, 19 | } 20 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Api/Semantics/Visibility.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.Compiler.Api.Semantics; 2 | 3 | /// 4 | /// The visibility of certain symbol. 5 | /// 6 | public enum Visibility 7 | { 8 | /// 9 | /// The symbol is visible only in the scope it was declared in. 10 | /// 11 | Private, 12 | 13 | /// 14 | /// The symbol is visible only in the assembly it was declared in. 15 | /// 16 | Internal, 17 | 18 | /// 19 | /// The symbol is visible both inside and outside of the assembly it was declared in. 20 | /// 21 | Public, 22 | } 23 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Api/Services/CodeCompletion/CompletionKind.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.Compiler.Api.Services.CodeCompletion; 2 | 3 | /// 4 | /// Categories for s that can be used to categorize the completions. 5 | /// 6 | public enum CompletionKind 7 | { 8 | DeclarationKeyword, 9 | VisibilityKeyword, 10 | ControlFlowKeyword, 11 | 12 | VariableName, 13 | ParameterName, 14 | ModuleName, 15 | FunctionName, 16 | PropertyName, 17 | FieldName, 18 | LabelName, 19 | 20 | TypeParameterName, 21 | ReferenceTypeName, 22 | ValueTypeName, 23 | 24 | Operator, 25 | } 26 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Api/Services/CodeFixes/CodeFix.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Immutable; 2 | using Draco.Compiler.Api.Syntax; 3 | 4 | namespace Draco.Compiler.Api.Services.CodeFixes; 5 | 6 | /// 7 | /// Represents a proposed codefix. 8 | /// 9 | public sealed class CodeFix(string displayText, ImmutableArray edits) 10 | { 11 | /// 12 | /// The user-friendly description of this . 13 | /// 14 | public string DisplayText { get; } = displayText; 15 | 16 | /// 17 | /// The s this will perform. 18 | /// 19 | public ImmutableArray Edits { get; } = edits; 20 | } 21 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Api/Services/Signature/SignatureItem.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Immutable; 2 | using Draco.Compiler.Api.Semantics; 3 | 4 | namespace Draco.Compiler.Api.Services.Signature; 5 | 6 | /// 7 | /// Represents signature information about a set of overloads. 8 | /// 9 | public sealed class SignatureItem( 10 | ImmutableArray overloads, 11 | IFunctionSymbol bestMatch, 12 | IParameterSymbol? currentParameter) 13 | { 14 | /// 15 | /// The function overloads that the signature is trying to resolve. 16 | /// 17 | public ImmutableArray Overloads { get; } = overloads; 18 | 19 | /// 20 | /// The currently best matching overload based on the parameters. 21 | /// 22 | public IFunctionSymbol BestMatch { get; } = bestMatch; 23 | 24 | /// 25 | /// The currently active parameter. 26 | /// 27 | public IParameterSymbol? CurrentParameter { get; } = currentParameter; 28 | } 29 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Api/Syntax/TextEdit.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.Compiler.Api.Syntax; 2 | 3 | /// 4 | /// Represents an edit in source code. 5 | /// 6 | /// The span of the text that will be replaced by . 7 | /// The text that should be inserted into the source text. 8 | public sealed record class TextEdit(SourceSpan Span, string Text); 9 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Api/Syntax/TriviaKind.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.Compiler.Api.Syntax; 2 | 3 | /// 4 | /// The different kinds of trivia. 5 | /// 6 | public enum TriviaKind 7 | { 8 | /// 9 | /// Any horizontal whitespace. 10 | /// 11 | Whitespace, 12 | 13 | /// 14 | /// Any newline sequence. 15 | /// 16 | Newline, 17 | 18 | /// 19 | /// Single line comments. 20 | /// 21 | LineComment, 22 | 23 | /// 24 | /// Documentation comment. 25 | /// 26 | DocumentationComment, 27 | } 28 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Draco.Compiler.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Binding/GlobalBinding.cs: -------------------------------------------------------------------------------- 1 | using Draco.Compiler.Internal.BoundTree; 2 | using Draco.Compiler.Internal.Symbols; 3 | 4 | namespace Draco.Compiler.Internal.Binding; 5 | 6 | /// 7 | /// The result of binding a global variable (field or property). 8 | /// 9 | /// The type of the global variable. 10 | /// The value of the global variable, if any. 11 | internal readonly record struct GlobalBinding(TypeSymbol Type, BoundExpression? Value); 12 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Binding/ImportItem.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Collections.Immutable; 3 | using Draco.Compiler.Api.Syntax; 4 | using Draco.Compiler.Internal.Symbols; 5 | 6 | namespace Draco.Compiler.Internal.Binding; 7 | 8 | /// 9 | /// Represents a single, resolved import. 10 | /// 11 | internal sealed class ImportItem( 12 | ImportDeclarationSyntax syntax, 13 | ImmutableArray> path, 14 | IEnumerable importedSymbols) 15 | { 16 | /// 17 | /// The syntax that created this import. 18 | /// 19 | public ImportDeclarationSyntax Syntax { get; } = syntax; 20 | 21 | /// 22 | /// The full, resolved path paired with each path syntax element. 23 | /// 24 | public ImmutableArray> Path { get; } = path; 25 | 26 | /// 27 | /// The imported symbols. 28 | /// 29 | public IEnumerable ImportedSymbols { get; } = importedSymbols; 30 | } 31 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Binding/IntrinsicsBinder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Draco.Compiler.Api; 4 | using Draco.Compiler.Api.Syntax; 5 | using Draco.Compiler.Internal.Symbols; 6 | 7 | namespace Draco.Compiler.Internal.Binding; 8 | 9 | /// 10 | /// Binds compiler-intrinsic symbols. 11 | /// 12 | internal sealed class IntrinsicsBinder : Binder 13 | { 14 | public override IEnumerable DeclaredSymbols => this.WellKnownTypes.AllSymbols; 15 | 16 | public IntrinsicsBinder(Compilation compilation) 17 | : base(compilation) 18 | { 19 | } 20 | 21 | public IntrinsicsBinder(Binder parent) 22 | : base(parent) 23 | { 24 | } 25 | 26 | internal override void LookupLocal(LookupResult result, string name, ref LookupFlags flags, Predicate allowSymbol, SyntaxNode? currentReference) 27 | { 28 | foreach (var symbol in this.DeclaredSymbols) 29 | { 30 | if (symbol.Name != name) continue; 31 | if (!allowSymbol(symbol)) continue; 32 | result.Add(symbol); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Binding/LookupFlags.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Draco.Compiler.Internal.Binding; 4 | 5 | /// 6 | /// Flags for looking up symbols. 7 | /// 8 | [Flags] 9 | internal enum LookupFlags 10 | { 11 | /// 12 | /// Default behavior. 13 | /// 14 | None = 0 << 0, 15 | 16 | /// 17 | /// Disallow looking up locals. 18 | /// 19 | DisallowLocals = 1 << 0, 20 | 21 | /// 22 | /// Allow looking up globals. 23 | /// 24 | AllowGlobals = 1 << 1, 25 | } 26 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Binding/Tasks/BindingTaskCompletionSource.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Draco.Compiler.Internal.Binding.Tasks; 4 | 5 | internal sealed class BindingTaskCompletionSource 6 | { 7 | public BindingTask Task 8 | { 9 | get 10 | { 11 | var task = new BindingTask 12 | { 13 | Awaiter = this.Awaiter 14 | }; 15 | return task; 16 | } 17 | } 18 | public bool IsCompleted => this.Awaiter.IsCompleted; 19 | public T Result => this.Awaiter.GetResult(); 20 | 21 | internal BindingTaskAwaiter Awaiter = new(); 22 | 23 | public BindingTaskAwaiter GetAwaiter() => this.Awaiter; 24 | public void SetResult(T result) => this.Awaiter.SetResult(result); 25 | public void SetException(Exception exception) => this.Awaiter.SetException(exception); 26 | } 27 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/BoundTree/BoundTreeFactory.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | 3 | namespace Draco.Compiler.Internal.BoundTree; 4 | 5 | [ExcludeFromCodeCoverage] 6 | internal partial class BoundTreeFactory 7 | { 8 | public static BoundAssignmentExpression AssignmentExpression(BoundLvalue left, BoundExpression right) => 9 | AssignmentExpression(null, left, right); 10 | } 11 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/BoundTree/BoundTreeVisitor.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | 3 | namespace Draco.Compiler.Internal.BoundTree; 4 | 5 | [ExcludeFromCodeCoverage] 6 | internal abstract partial class BoundTreeVisitor 7 | { 8 | } 9 | 10 | [ExcludeFromCodeCoverage] 11 | internal abstract partial class BoundTreeVisitor 12 | { 13 | } 14 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Codegen/AllocatedLocal.cs: -------------------------------------------------------------------------------- 1 | using Draco.Compiler.Internal.Symbols; 2 | 3 | namespace Draco.Compiler.Internal.Codegen; 4 | 5 | /// 6 | /// Some method-local variable allocation. 7 | /// 8 | /// The corresponding local symbol. 9 | /// The index of the local within the method. 10 | internal readonly record struct AllocatedLocal(LocalSymbol Symbol, int Index); 11 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Codegen/CodegenErrors.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | using Draco.Compiler.Api.Diagnostics; 3 | using Draco.Compiler.Internal.Diagnostics; 4 | 5 | namespace Draco.Compiler.Internal.Codegen; 6 | 7 | [ExcludeFromCodeCoverage] 8 | internal static class CodegenErrors 9 | { 10 | private static string Code(int index) => DiagnosticTemplate.CreateDiagnosticCode(DiagnosticCategory.Codegen, index); 11 | 12 | /// 13 | /// Scripting engine could not find main. 14 | /// 15 | public static readonly DiagnosticTemplate NoMainMethod = DiagnosticTemplate.Create( 16 | title: "no main method found", 17 | severity: DiagnosticSeverity.Error, 18 | format: "no main method found in compiled assembly", 19 | code: Code(1)); 20 | } 21 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Codegen/CodegenFlags.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Draco.Compiler.Internal.Codegen; 4 | 5 | /// 6 | /// Flags for code generation. 7 | /// 8 | [Flags] 9 | internal enum CodegenFlags 10 | { 11 | /// 12 | /// No flags. 13 | /// 14 | None = 0, 15 | 16 | /// 17 | /// Emit PDB information. 18 | /// 19 | EmitPdb = (1 << 0), 20 | 21 | /// 22 | /// Attempt to recover stack-structure from register-based code, potentially causing less instructions to be emitted. 23 | /// 24 | Stackify = (1 << 1), 25 | 26 | /// 27 | /// Redirect all source references to the root module. 28 | /// 29 | RedirectHandlesToRoot = (1 << 2), 30 | } 31 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Codegen/SequencePoint.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection.Metadata; 2 | 3 | namespace Draco.Compiler.Internal.Codegen; 4 | 5 | internal readonly record struct SequencePoint( 6 | DocumentHandle Document, 7 | int IlOffset, 8 | int StartLine, 9 | int StartColumn, 10 | int EndLine, 11 | int EndColumn) 12 | { 13 | public static SequencePoint Hidden(int ilOffset) => Hidden(default, ilOffset); 14 | 15 | public static SequencePoint Hidden(DocumentHandle document, int ilOffset) => new( 16 | Document: document, 17 | IlOffset: ilOffset, 18 | StartLine: 0xfeefee, 19 | EndLine: 0xfeefee, 20 | StartColumn: 0, 21 | EndColumn: 0); 22 | 23 | public SequencePoint(int ilOffset, int startLine, int startColumn, int endLine, int endColumn) 24 | : this(default, ilOffset, startLine, startColumn, endLine, endColumn) 25 | { 26 | } 27 | 28 | public bool IsHidden => 29 | this.StartLine == 0xfeefee 30 | && this.EndLine == 0xfeefee 31 | && this.StartColumn == 0 32 | && this.EndColumn == 0; 33 | } 34 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Declarations/Declaration.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Collections.Immutable; 3 | using Draco.Compiler.Api.Syntax; 4 | 5 | namespace Draco.Compiler.Internal.Declarations; 6 | 7 | /// 8 | /// Represents any kind of top-level declaration in the source code. 9 | /// 10 | internal abstract class Declaration(string name) 11 | { 12 | /// 13 | /// The name of the declared element. 14 | /// 15 | public string Name { get; } = name; 16 | 17 | /// 18 | /// The declarations within this one. 19 | /// 20 | public abstract ImmutableArray Children { get; } 21 | 22 | /// 23 | /// The syntaxes that contribute to this declaration. 24 | /// 25 | public abstract IEnumerable DeclaringSyntaxes { get; } 26 | } 27 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Declarations/FunctionDeclaration.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Collections.Immutable; 3 | using Draco.Compiler.Api.Syntax; 4 | 5 | namespace Draco.Compiler.Internal.Declarations; 6 | 7 | /// 8 | /// A free-function declaration. 9 | /// 10 | internal sealed class FunctionDeclaration(FunctionDeclarationSyntax syntax) 11 | : Declaration(syntax.Name.Text) 12 | { 13 | /// 14 | /// The syntax of the declaration. 15 | /// 16 | public FunctionDeclarationSyntax Syntax { get; } = syntax; 17 | 18 | public override ImmutableArray Children => []; 19 | 20 | public override IEnumerable DeclaringSyntaxes => [this.Syntax]; 21 | } 22 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Declarations/GlobalDeclaration.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Collections.Immutable; 3 | using Draco.Compiler.Api.Syntax; 4 | 5 | namespace Draco.Compiler.Internal.Declarations; 6 | 7 | /// 8 | /// A global variable declaration. 9 | /// 10 | internal sealed class GlobalDeclaration(VariableDeclarationSyntax syntax) 11 | : Declaration(syntax.Name.Text) 12 | { 13 | /// 14 | /// The syntax of the declaration. 15 | /// 16 | public VariableDeclarationSyntax Syntax { get; } = syntax; 17 | 18 | public override ImmutableArray Children => []; 19 | 20 | public override IEnumerable DeclaringSyntaxes => [this.Syntax]; 21 | } 22 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Diagnostics/ConcurrentDiagnosticBag.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Concurrent; 2 | using System.Collections.Generic; 3 | using Draco.Compiler.Api.Diagnostics; 4 | 5 | namespace Draco.Compiler.Internal.Diagnostics; 6 | 7 | /// 8 | /// Holds diagnostic messages in a concurrent context. 9 | /// 10 | internal sealed class ConcurrentDiagnosticBag : DiagnosticBag 11 | { 12 | public override int Count => this.diagnostics.Count; 13 | 14 | private readonly ConcurrentBag diagnostics = []; 15 | 16 | public override void Add(Diagnostic diagnostic) => this.diagnostics.Add(diagnostic); 17 | public override void Clear() => this.diagnostics.Clear(); 18 | public override IEnumerator GetEnumerator() => this.diagnostics.GetEnumerator(); 19 | } 20 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Diagnostics/DiagnosticCategory.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.Compiler.Internal.Diagnostics; 2 | 3 | /// 4 | /// Possible categories of diagnostic. 5 | /// 6 | internal enum DiagnosticCategory 7 | { 8 | InternalCompiler = 0, 9 | Syntax = 1, 10 | SymbolResolution = 2, 11 | TypeChecking = 3, 12 | ConstantEvaluation = 4, 13 | FlowAnalysis = 5, 14 | Codegen = 6, 15 | } 16 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Diagnostics/EmptyDiagnosticBag.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using Draco.Compiler.Api.Diagnostics; 4 | 5 | namespace Draco.Compiler.Internal.Diagnostics; 6 | 7 | /// 8 | /// A diagnostic bag that stays empty. 9 | /// 10 | internal sealed class EmptyDiagnosticBag : DiagnosticBag 11 | { 12 | /// 13 | /// A singleton instance of . 14 | /// 15 | public static EmptyDiagnosticBag Instance { get; } = new(); 16 | 17 | public override int Count => 0; 18 | 19 | private EmptyDiagnosticBag() 20 | { 21 | } 22 | 23 | public override void Add(Diagnostic diagnostic) { } 24 | public override void Clear() { } 25 | public override IEnumerator GetEnumerator() => Enumerable.Empty().GetEnumerator(); 26 | } 27 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Evaluation/EvaluationErrors.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | using Draco.Compiler.Api.Diagnostics; 3 | using Draco.Compiler.Internal.Diagnostics; 4 | 5 | namespace Draco.Compiler.Internal.Evaluation; 6 | 7 | /// 8 | /// Error messages for the evaluation phase. 9 | /// 10 | [ExcludeFromCodeCoverage] 11 | internal static class EvaluationErrors 12 | { 13 | private static string Code(int index) => DiagnosticTemplate.CreateDiagnosticCode(DiagnosticCategory.ConstantEvaluation, index); 14 | 15 | /// 16 | /// The expression is not a valid constant expression. 17 | /// 18 | public static readonly DiagnosticTemplate NotConstant = DiagnosticTemplate.Create( 19 | title: "not a constant", 20 | severity: DiagnosticSeverity.Error, 21 | format: "the expression is not a valid constant expression", 22 | code: Code(1)); 23 | } 24 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/OptimizingIr/Codegen/MinimalModuleSymbol.cs: -------------------------------------------------------------------------------- 1 | using Draco.Compiler.Internal.Symbols; 2 | 3 | namespace Draco.Compiler.Internal.OptimizingIr.Codegen; 4 | 5 | /// 6 | /// A minimal implementation of that only contains a name. 7 | /// Used by to back the root module. 8 | /// 9 | internal sealed class MinimalModuleSymbol(string name) : ModuleSymbol 10 | { 11 | public override Api.Semantics.Visibility Visibility => Api.Semantics.Visibility.Public; 12 | public override string Name => name; 13 | } 14 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/OptimizingIr/Instructions/AddressOfInstruction.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Draco.Compiler.Internal.OptimizingIr.Model; 3 | using Draco.Compiler.Internal.Symbols; 4 | 5 | namespace Draco.Compiler.Internal.OptimizingIr.Instructions; 6 | 7 | /// 8 | /// Loads the address of some local/global/argument. 9 | /// 10 | internal sealed class AddressOfInstruction(Register target, Symbol source) 11 | : InstructionBase, IValueInstruction 12 | { 13 | public override string InstructionKeyword => "addressof"; 14 | 15 | public Register Target { get; set; } = target; 16 | 17 | /// 18 | /// The operand to load from. 19 | /// 20 | public Symbol Source { get; set; } = source; 21 | 22 | public override IEnumerable StaticOperands => [this.Source]; 23 | 24 | public override string ToString() => 25 | $"{this.Target.ToOperandString()} := {this.InstructionKeyword} {this.Source.FullName}"; 26 | 27 | public override AddressOfInstruction Clone() => new(this.Target, this.Source); 28 | } 29 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/OptimizingIr/Instructions/ArithmeticOp.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.Compiler.Internal.OptimizingIr.Instructions; 2 | 3 | /// 4 | /// The different arithmetic operations supported. 5 | /// 6 | internal enum ArithmeticOp 7 | { 8 | /// 9 | /// Arithmetic addition. 10 | /// 11 | Add, 12 | 13 | /// 14 | /// Arithmetic subtraction. 15 | /// 16 | Sub, 17 | 18 | /// 19 | /// Arithmetic multiplication. 20 | /// 21 | Mul, 22 | 23 | /// 24 | /// Arithmetic division. 25 | /// 26 | Div, 27 | 28 | /// 29 | /// Arithmetic remainder. 30 | /// 31 | Rem, 32 | 33 | /// 34 | /// Less-than comparison. 35 | /// 36 | Less, 37 | 38 | /// 39 | /// Equality comparison. 40 | /// 41 | Equal, 42 | } 43 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/OptimizingIr/Instructions/ArrayLengthInstruction.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Draco.Compiler.Internal.OptimizingIr.Model; 3 | 4 | namespace Draco.Compiler.Internal.OptimizingIr.Instructions; 5 | 6 | /// 7 | /// An array length query. 8 | /// 9 | internal sealed class ArrayLengthInstruction(Register target, IOperand array) 10 | : InstructionBase, IValueInstruction 11 | { 12 | public override string InstructionKeyword => "length"; 13 | 14 | public Register Target { get; set; } = target; 15 | 16 | /// 17 | /// The array to get the length of. 18 | /// 19 | public IOperand Array { get; set; } = array; 20 | 21 | public override IEnumerable Operands => [this.Array]; 22 | 23 | public override string ToString() => 24 | $"{this.Target.ToOperandString()} := {this.InstructionKeyword} {this.Array.ToOperandString()}"; 25 | 26 | public override ArrayLengthInstruction Clone() => new(this.Target, this.Array); 27 | } 28 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/OptimizingIr/Instructions/EndScope.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.Compiler.Internal.OptimizingIr.Instructions; 2 | 3 | /// 4 | /// A pseudo-instruction for representing the end of a local scope. 5 | /// 6 | internal sealed class EndScope : InstructionBase 7 | { 8 | public override string InstructionKeyword => "@scope end"; 9 | 10 | public override bool IsValidInUnreachableContext => true; 11 | 12 | public override EndScope Clone() => new(); 13 | 14 | public override string ToString() => this.InstructionKeyword; 15 | } 16 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/OptimizingIr/Instructions/IValueInstruction.cs: -------------------------------------------------------------------------------- 1 | using Draco.Compiler.Internal.OptimizingIr.Model; 2 | 3 | namespace Draco.Compiler.Internal.OptimizingIr.Instructions; 4 | 5 | /// 6 | /// An instruction that produces a result in a register. 7 | /// 8 | internal interface IValueInstruction : IInstruction 9 | { 10 | /// 11 | /// The register to store the result at. 12 | /// 13 | public Register Target { get; } 14 | } 15 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/OptimizingIr/Instructions/JumpInstruction.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Draco.Compiler.Internal.OptimizingIr.Model; 3 | 4 | namespace Draco.Compiler.Internal.OptimizingIr.Instructions; 5 | 6 | /// 7 | /// An unconditional jump. 8 | /// 9 | internal sealed class JumpInstruction(BasicBlock target) : InstructionBase 10 | { 11 | public override string InstructionKeyword => "jump"; 12 | public override bool IsBranch => true; 13 | public override IEnumerable JumpTargets => [this.Target]; 14 | 15 | /// 16 | /// The jump target. 17 | /// 18 | public BasicBlock Target { get; set; } = target; 19 | 20 | public override string ToString() => $"{this.InstructionKeyword} lbl{this.Target.Index}"; 21 | 22 | public override JumpInstruction Clone() => new(this.Target); 23 | } 24 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/OptimizingIr/Instructions/LoadInstruction.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Draco.Compiler.Internal.OptimizingIr.Model; 3 | using Draco.Compiler.Internal.Symbols; 4 | 5 | namespace Draco.Compiler.Internal.OptimizingIr.Instructions; 6 | 7 | /// 8 | /// Loads a value from a local/global/argument. 9 | /// 10 | internal sealed class LoadInstruction(Register target, Symbol source) 11 | : InstructionBase, IValueInstruction 12 | { 13 | public override string InstructionKeyword => "load"; 14 | 15 | public Register Target { get; set; } = target; 16 | 17 | /// 18 | /// The operand to load from. 19 | /// 20 | public Symbol Source { get; set; } = source; 21 | 22 | public override IEnumerable StaticOperands => [this.Source]; 23 | 24 | public override string ToString() => 25 | $"{this.Target.ToOperandString()} := {this.InstructionKeyword} {this.Source.FullName}"; 26 | 27 | public override LoadInstruction Clone() => new(this.Target, this.Source); 28 | } 29 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/OptimizingIr/Instructions/NopInstruction.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.Compiler.Internal.OptimizingIr.Instructions; 2 | 3 | /// 4 | /// Represents no operation. 5 | /// 6 | internal sealed class NopInstruction : InstructionBase 7 | { 8 | public override string InstructionKeyword => "nop"; 9 | 10 | public override string ToString() => this.InstructionKeyword; 11 | 12 | public override NopInstruction Clone() => new(); 13 | } 14 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/OptimizingIr/Instructions/RetInstruction.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Draco.Compiler.Internal.OptimizingIr.Model; 3 | 4 | namespace Draco.Compiler.Internal.OptimizingIr.Instructions; 5 | 6 | /// 7 | /// Returns from the current procedure. 8 | /// 9 | internal sealed class RetInstruction(IOperand value) : InstructionBase 10 | { 11 | public override string InstructionKeyword => "ret"; 12 | 13 | public override bool IsBranch => true; 14 | 15 | /// 16 | /// The returned value. 17 | /// 18 | public IOperand Value { get; set; } = value; 19 | 20 | public override IEnumerable Operands => [this.Value]; 21 | 22 | public override string ToString() => $"{this.InstructionKeyword} {this.Value.ToOperandString()}"; 23 | 24 | public override RetInstruction Clone() => new(this.Value); 25 | } 26 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/OptimizingIr/Model/Constant.cs: -------------------------------------------------------------------------------- 1 | using Draco.Compiler.Internal.Symbols; 2 | using Draco.Compiler.Internal.Utilities; 3 | 4 | namespace Draco.Compiler.Internal.OptimizingIr.Model; 5 | 6 | /// 7 | /// A constant value. 8 | /// 9 | /// The constant value. 10 | /// The type of the constant. 11 | internal readonly record struct Constant(object? Value, TypeSymbol Type) : IOperand 12 | { 13 | public override string ToString() => this.ToOperandString(); 14 | public string ToOperandString() => this.Value switch 15 | { 16 | string s => $"\"{StringUtils.Unescape(s)}\"", 17 | bool b => b ? "true" : "false", 18 | _ => this.Value?.ToString() ?? "null", 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/OptimizingIr/Model/DefaultValue.cs: -------------------------------------------------------------------------------- 1 | using Draco.Compiler.Internal.Symbols; 2 | 3 | namespace Draco.Compiler.Internal.OptimizingIr.Model; 4 | 5 | /// 6 | /// Represents the default value of a type. 7 | /// 8 | /// The type the default value corresponds to. 9 | internal readonly record struct DefaultValue(TypeSymbol Type) : IOperand 10 | { 11 | public string ToOperandString() => $"default({this.Type})"; 12 | } 13 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/OptimizingIr/Model/IAssembly.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.Compiler.Internal.OptimizingIr.Model; 2 | 3 | /// 4 | /// Read-only interface of a program. 5 | /// 6 | internal interface IAssembly 7 | { 8 | /// 9 | /// The root module of this assembly. 10 | /// 11 | public IModule RootModule { get; } 12 | 13 | /// 14 | /// The name of this assembly. 15 | /// 16 | public string Name { get; } 17 | 18 | /// 19 | /// The entry point of this assembly. 20 | /// 21 | public IProcedure? EntryPoint { get; } 22 | } 23 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/OptimizingIr/Model/IOperand.cs: -------------------------------------------------------------------------------- 1 | using Draco.Compiler.Internal.Symbols; 2 | 3 | namespace Draco.Compiler.Internal.OptimizingIr.Model; 4 | 5 | /// 6 | /// The interface of all operands that an instruction can hold. 7 | /// 8 | internal interface IOperand 9 | { 10 | /// 11 | /// The type of this operand. 12 | /// 13 | public TypeSymbol Type { get; } 14 | 15 | /// 16 | /// Returns a string representation of the operand. 17 | /// 18 | /// The reason that is not used is because some entities are printed 19 | /// with , when they are not operands, for example procedures and basic blocks. 20 | /// 21 | /// The string representation of this operand. 22 | public string ToOperandString(); 23 | } 24 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/OptimizingIr/Model/ModelExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using Draco.Compiler.Internal.Symbols; 4 | 5 | namespace Draco.Compiler.Internal.OptimizingIr.Model; 6 | 7 | /// 8 | /// Extension functionality for the IR model. 9 | /// 10 | internal static class ModelExtensions 11 | { 12 | /// 13 | /// Retrieves all functions that are statically referenced by a given procedure. 14 | /// 15 | /// The procedure to retrieve the referenced functions from. 16 | /// The referenced functions. 17 | public static IEnumerable GetReferencedFunctions(this IProcedure procedure) => procedure.BasicBlocks.Values 18 | .SelectMany(bb => bb.Instructions) 19 | .SelectMany(instr => instr.StaticOperands) 20 | .OfType() 21 | .Select(f => f.IsGenericInstance ? f.GenericDefinition! : f) 22 | .Distinct(); 23 | } 24 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/OptimizingIr/Model/Register.cs: -------------------------------------------------------------------------------- 1 | using Draco.Compiler.Internal.Symbols; 2 | 3 | namespace Draco.Compiler.Internal.OptimizingIr.Model; 4 | 5 | /// 6 | /// An immutable register for temporary-value computations. 7 | /// 8 | /// The type this register holds. 9 | /// The register index. 10 | internal readonly record struct Register(TypeSymbol Type, int Index) : IOperand 11 | { 12 | public override string ToString() => this.ToOperandString(); 13 | public string ToOperandString() => $"r{this.Index}"; 14 | 15 | public bool Equals(Register other) => this.Index == other.Index; 16 | public override int GetHashCode() => this.Index.GetHashCode(); 17 | } 18 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/OptimizingIr/Model/Void.cs: -------------------------------------------------------------------------------- 1 | using Draco.Compiler.Internal.Symbols; 2 | 3 | namespace Draco.Compiler.Internal.OptimizingIr.Model; 4 | 5 | /// 6 | /// Represents no value. 7 | /// 8 | internal readonly record struct Void : IOperand 9 | { 10 | public TypeSymbol Type => WellKnownTypes.Unit; 11 | 12 | public override string ToString() => this.ToOperandString(); 13 | public string ToOperandString() => "unit"; 14 | } 15 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/OptimizingIr/OptimizationPipeline.cs: -------------------------------------------------------------------------------- 1 | using Draco.Compiler.Internal.OptimizingIr.Passes; 2 | using static Draco.Compiler.Internal.OptimizingIr.PassFactory; 3 | 4 | namespace Draco.Compiler.Internal.OptimizingIr; 5 | 6 | /// 7 | /// Builds up the whole optimization pipeline. 8 | /// 9 | internal static class OptimizationPipeline 10 | { 11 | public static IPass Instance { get; } = Fixpoint(Sequence( 12 | Fixpoint(JumpThreading.Instance), 13 | DeadBlockElimination.Instance)); 14 | } 15 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/OptimizingIr/Passes/DeadBlockElimination.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using Draco.Compiler.Internal.Utilities; 3 | 4 | namespace Draco.Compiler.Internal.OptimizingIr.Passes; 5 | 6 | /// 7 | /// We simply remove basic blocks that are never referenced. 8 | /// 9 | internal static class DeadBlockElimination 10 | { 11 | public static IPass Instance { get; } = PassFactory.Procedure(procedure => 12 | { 13 | var referenced = GraphTraversal.DepthFirst( 14 | start: procedure.Entry, 15 | getNeighbors: bb => bb.Successors); 16 | var notReferenced = procedure.BasicBlocks.Values 17 | .Except(referenced) 18 | .ToList(); 19 | var changed = false; 20 | foreach (var bb in notReferenced) changed = procedure.RemoveBasicBlock(bb) || changed; 21 | return changed; 22 | }); 23 | } 24 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/OptimizingIr/Passes/IPass.cs: -------------------------------------------------------------------------------- 1 | using Draco.Compiler.Internal.OptimizingIr.Model; 2 | 3 | namespace Draco.Compiler.Internal.OptimizingIr.Passes; 4 | 5 | /// 6 | /// A pass over the IR code. 7 | /// 8 | internal interface IPass 9 | { 10 | /// 11 | /// Applies the pass to the given . 12 | /// 13 | /// The to apply the pass to. 14 | /// True, if the pass changed something. 15 | public bool Apply(Assembly assembly); 16 | } 17 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Solver/Constraints/Assignable.cs: -------------------------------------------------------------------------------- 1 | using Draco.Compiler.Internal.Binding; 2 | using Draco.Compiler.Internal.Symbols; 3 | 4 | namespace Draco.Compiler.Internal.Solver.Constraints; 5 | 6 | /// 7 | /// Constraint asserting that one type is assignable to another type. 8 | /// 9 | /// The locator of the constraint. 10 | /// The type being assigned to. 11 | /// The type assigned. 12 | internal sealed class Assignable( 13 | ConstraintLocator? locator, 14 | TypeSymbol targetType, 15 | TypeSymbol assignedType) : Constraint(locator, TypeCheckingErrors.TypeMismatch) 16 | { 17 | /// 18 | /// The type being assigned to. 19 | /// 20 | public TypeSymbol TargetType { get; } = targetType; 21 | 22 | /// 23 | /// The type assigned. 24 | /// 25 | public TypeSymbol AssignedType { get; } = assignedType; 26 | } 27 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Solver/Constraints/Same.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Immutable; 2 | using Draco.Compiler.Internal.Binding; 3 | using Draco.Compiler.Internal.Symbols; 4 | 5 | namespace Draco.Compiler.Internal.Solver.Constraints; 6 | 7 | /// 8 | /// Asserts that a set of types are all the same. 9 | /// 10 | /// The locator of the constraint. 11 | /// The types that all should be the same. 12 | internal sealed class Same( 13 | ConstraintLocator? locator, 14 | ImmutableArray types) : Constraint(locator, TypeCheckingErrors.TypeMismatch) 15 | { 16 | /// 17 | /// The types that all should be the same. 18 | /// 19 | public ImmutableArray Types { get; } = types; 20 | } 21 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Solver/OverloadResolution/Argument.cs: -------------------------------------------------------------------------------- 1 | using Draco.Compiler.Api.Syntax; 2 | using Draco.Compiler.Internal.Symbols; 3 | 4 | namespace Draco.Compiler.Internal.Solver.OverloadResolution; 5 | 6 | /// 7 | /// Represents an argument to a function. 8 | /// 9 | /// The syntax of the argument. 10 | /// The type of the argument. 11 | internal readonly record struct Argument(SyntaxNode? Syntax, TypeSymbol Type); 12 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Solver/OverloadResolution/CallScoreComparison.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.Compiler.Internal.Solver.OverloadResolution; 2 | 3 | /// 4 | /// Represents the comparison result of two s. 5 | /// 6 | internal enum CallScoreComparison 7 | { 8 | /// 9 | /// The relationship could not be determined, because the scores are not well-defined. 10 | /// 11 | Undetermined, 12 | 13 | /// 14 | /// The first score vector dominates the second. 15 | /// 16 | FirstDominates, 17 | 18 | /// 19 | /// The second score vector dominates the first. 20 | /// 21 | SecondDominates, 22 | 23 | /// 24 | /// There is mutual non-dominance. 25 | /// 26 | NoDominance, 27 | 28 | /// 29 | /// The two scores are equal. 30 | /// 31 | Equal, 32 | } 33 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Solver/Tasks/SolverTask.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Collections.Immutable; 3 | using System.Runtime.CompilerServices; 4 | 5 | namespace Draco.Compiler.Internal.Solver.Tasks; 6 | 7 | internal static class SolverTask 8 | { 9 | public static SolverTask FromResult(T result) 10 | { 11 | var task = new SolverTask(); 12 | task.Awaiter.SetResult(result); 13 | return task; 14 | } 15 | 16 | public static async SolverTask> WhenAll(IEnumerable> tasks) 17 | { 18 | var result = ImmutableArray.CreateBuilder(); 19 | foreach (var task in tasks) result.Add(await task); 20 | return result.ToImmutable(); 21 | } 22 | } 23 | 24 | [AsyncMethodBuilder(typeof(SolverTaskMethodBuilder<>))] 25 | internal sealed class SolverTask 26 | { 27 | internal SolverTaskAwaiter Awaiter = new(); 28 | public bool IsCompleted => this.Awaiter.IsCompleted; 29 | public T Result => this.Awaiter.GetResult(); 30 | public SolverTaskAwaiter GetAwaiter() => this.Awaiter; 31 | } 32 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Solver/Tasks/SolverTaskCompletionSource.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Draco.Compiler.Internal.Solver.Tasks; 4 | 5 | internal sealed class SolverTaskCompletionSource 6 | { 7 | public SolverTask Task 8 | { 9 | get 10 | { 11 | var task = new SolverTask 12 | { 13 | Awaiter = this.Awaiter 14 | }; 15 | return task; 16 | } 17 | } 18 | public bool IsCompleted => this.Awaiter.IsCompleted; 19 | public T Result => this.Awaiter.GetResult(); 20 | 21 | internal SolverTaskAwaiter Awaiter = new(); 22 | 23 | public SolverTaskAwaiter GetAwaiter() => this.Awaiter; 24 | public void SetResult(T result) => this.Awaiter.SetResult(result); 25 | public void SetException(Exception exception) => this.Awaiter.SetException(exception); 26 | } 27 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Symbols/ConstantValue.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.Compiler.Internal.Symbols; 2 | 3 | /// 4 | /// A constant value. 5 | /// 6 | /// The type of the argument. 7 | /// The value of the argument. 8 | internal readonly record struct ConstantValue(TypeSymbol Type, object? Value); 9 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Symbols/Error/ErrorIndexerPropertySymbol.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.Compiler.Internal.Symbols.Error; 2 | 3 | /// 4 | /// An error indexer property symbol. 5 | /// 6 | /// The number of indices the indexer property takes. 7 | internal sealed class ErrorIndexerPropertySymbol(int indicesCount) : ErrorPropertySymbol 8 | { 9 | public override bool IsIndexer => true; 10 | protected override int ParameterCount => indicesCount; 11 | } 12 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Symbols/Error/ErrorLabelSymbol.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.Compiler.Internal.Symbols.Error; 2 | 3 | /// 4 | /// Represents label reference that has an error - for example, it does not exist. 5 | /// 6 | internal sealed class ErrorLabelSymbol(string name) : LabelSymbol 7 | { 8 | public override bool IsError => true; 9 | 10 | public override string Name { get; } = name; 11 | } 12 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Symbols/Error/ErrorPropertyAccessorSymbol.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.Compiler.Internal.Symbols.Error; 2 | 3 | /// 4 | /// Represents a property accessor with an error - for example, it was not defined. 5 | /// 6 | internal sealed class ErrorPropertyAccessorSymbol(PropertySymbol property, int parameterCount = 0) 7 | : ErrorFunctionSymbol(parameterCount), IPropertyAccessorSymbol 8 | { 9 | public override bool IsStatic => true; 10 | public override Api.Semantics.Visibility Visibility => Api.Semantics.Visibility.Public; 11 | public PropertySymbol Property { get; } = property; 12 | } 13 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Symbols/Error/ErrorTypeSymbol.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Immutable; 2 | using Draco.Compiler.Internal.Symbols.Generic; 3 | 4 | namespace Draco.Compiler.Internal.Symbols.Error; 5 | 6 | /// 7 | /// Represents a type of some type-checking error. Acts as a sentinel value, absorbs cascading errors. 8 | /// 9 | internal sealed class ErrorTypeSymbol(string name) : TypeSymbol 10 | { 11 | public override bool IsError => true; 12 | public override Api.Semantics.Visibility Visibility => Api.Semantics.Visibility.Public; 13 | 14 | /// 15 | /// The display name of the type. 16 | /// 17 | public string DisplayName { get; } = name; 18 | 19 | public override string ToString() => this.DisplayName; 20 | 21 | public override TypeSymbol GenericInstantiate(Symbol? containingSymbol, ImmutableArray arguments) => this; 22 | public override TypeSymbol GenericInstantiate(Symbol? containingSymbol, GenericContext context) => this; 23 | } 24 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Symbols/Error/ErrorValueSymbol.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.Compiler.Internal.Symbols.Error; 2 | 3 | /// 4 | /// Represents a faulty in-source value reference - like a local variable. 5 | /// 6 | internal sealed class ErrorValueSymbol(string name) : Symbol, ITypedSymbol 7 | { 8 | public override bool IsError => true; 9 | public override Symbol? ContainingSymbol => null; 10 | public override Api.Semantics.Visibility Visibility => Api.Semantics.Visibility.Public; 11 | public override Api.Semantics.SymbolKind Kind => Api.Semantics.SymbolKind.Field; 12 | 13 | public override string Name { get; } = name; 14 | 15 | public TypeSymbol Type => WellKnownTypes.ErrorType; 16 | 17 | public override Api.Semantics.ISymbol ToApiSymbol() => new Api.Semantics.AnySymbol(this); 18 | 19 | public override void Accept(SymbolVisitor visitor) => throw new System.NotSupportedException(); 20 | public override TResult Accept(SymbolVisitor visitor) => throw new System.NotSupportedException(); 21 | } 22 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Symbols/FunctionTypeSymbol.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Immutable; 2 | 3 | namespace Draco.Compiler.Internal.Symbols; 4 | 5 | /// 6 | /// Represents a function type. 7 | /// 8 | internal sealed class FunctionTypeSymbol( 9 | ImmutableArray parameters, 10 | TypeSymbol returnType) : TypeSymbol 11 | { 12 | /// 13 | /// The parameters of the function. 14 | /// 15 | public ImmutableArray Parameters { get; } = parameters; 16 | 17 | /// 18 | /// The return type of the function. 19 | /// 20 | public TypeSymbol ReturnType { get; } = returnType; 21 | 22 | public override string ToString() => 23 | $"({string.Join(", ", this.Parameters)}) -> {this.ReturnType}"; 24 | } 25 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Symbols/Generic/IGenericInstanceSymbol.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.Compiler.Internal.Symbols.Generic; 2 | 3 | /// 4 | /// Any symbol that is in a generic instantiated context. 5 | /// 6 | internal interface IGenericInstanceSymbol 7 | { 8 | /// 9 | /// The generic context introduced. 10 | /// 11 | public GenericContext Context { get; } 12 | } 13 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Symbols/Generic/PropertyAccessorInstanceSymbol.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.Compiler.Internal.Symbols.Generic; 2 | 3 | /// 4 | /// Represents a generic instantiated property accessor. 5 | /// It does not necessarily mean that the property accessor itself was generic, it might have been within another generic 6 | /// context (like a generic type definition). 7 | /// 8 | internal sealed class PropertyAccessorInstanceSymbol( 9 | Symbol? containingSymbol, 10 | FunctionSymbol genericDefinition, 11 | GenericContext context, 12 | PropertySymbol property) 13 | : FunctionInstanceSymbol(containingSymbol, genericDefinition, context), IPropertyAccessorSymbol 14 | { 15 | public PropertySymbol Property { get; } = property; 16 | public override Api.Semantics.Visibility Visibility => this.GenericDefinition.Visibility; 17 | } 18 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Symbols/IMemberSymbol.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.Compiler.Internal.Symbols; 2 | 3 | /// 4 | /// Represents any member symbol. 5 | /// 6 | internal interface IMemberSymbol 7 | { 8 | /// 9 | /// Specifying if the given symbol is static. 10 | /// 11 | public bool IsStatic { get; } 12 | 13 | /// 14 | /// True if this member is an explicit implementation of an interface member. 15 | /// 16 | public bool IsExplicitImplementation { get; } 17 | } 18 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Symbols/IOverridableSymbol.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.Compiler.Internal.Symbols; 2 | 3 | /// 4 | /// Represents any symbol that can be overridden. 5 | /// 6 | internal interface IOverridableSymbol 7 | { 8 | /// 9 | /// Represents the overridden symbol. 10 | /// Null, if this symbol doesn't override anything. 11 | /// 12 | public Symbol? Override { get; } 13 | 14 | /// 15 | /// Checks if can be override of this symbol. 16 | /// 17 | /// The symbol that could be override of this symbol. 18 | /// True, if can be override of this symbol, otherwise false. 19 | public bool CanBeOverriddenBy(IOverridableSymbol other); 20 | } 21 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Symbols/IPropertyAccessorSymbol.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.Compiler.Internal.Symbols; 2 | 3 | /// 4 | /// Represents an property accessor symbol, for example get, set and init accessors in c#. This interface is intended to be used while also inheriting . 5 | /// 6 | internal interface IPropertyAccessorSymbol 7 | { 8 | /// 9 | /// The property that uses this accessor. 10 | /// 11 | public PropertySymbol Property { get; } 12 | } 13 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Symbols/ITypedSymbol.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.Compiler.Internal.Symbols; 2 | 3 | /// 4 | /// Represents any symbol that has a type associated with it. 5 | /// 6 | internal interface ITypedSymbol 7 | { 8 | /// 9 | /// The type of value the symbol references. 10 | /// 11 | public TypeSymbol Type { get; } 12 | } 13 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Symbols/LabelSymbol.cs: -------------------------------------------------------------------------------- 1 | using Draco.Compiler.Api.Semantics; 2 | 3 | namespace Draco.Compiler.Internal.Symbols; 4 | 5 | /// 6 | /// Represents a label. 7 | /// 8 | internal abstract partial class LabelSymbol : Symbol 9 | { 10 | public override SymbolKind Kind => SymbolKind.Label; 11 | 12 | public override ISymbol ToApiSymbol() => new Api.Semantics.LabelSymbol(this); 13 | 14 | public override void Accept(SymbolVisitor visitor) => visitor.VisitLabel(this); 15 | public override TResult Accept(SymbolVisitor visitor) => visitor.VisitLabel(this); 16 | } 17 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Symbols/LocalSymbol.cs: -------------------------------------------------------------------------------- 1 | using Draco.Compiler.Api.Semantics; 2 | 3 | namespace Draco.Compiler.Internal.Symbols; 4 | 5 | /// 6 | /// A local variable. 7 | /// 8 | internal abstract partial class LocalSymbol : VariableSymbol 9 | { 10 | public override SymbolKind Kind => SymbolKind.Local; 11 | 12 | public override ISymbol ToApiSymbol() => new Api.Semantics.LocalSymbol(this); 13 | 14 | public override void Accept(SymbolVisitor visitor) => visitor.VisitLocal(this); 15 | public override TResult Accept(SymbolVisitor visitor) => visitor.VisitLocal(this); 16 | } 17 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Symbols/Metadata/IMetadataSymbol.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection.Metadata; 2 | 3 | namespace Draco.Compiler.Internal.Symbols.Metadata; 4 | 5 | /// 6 | /// Represents a symbol loaded from metadata. 7 | /// 8 | internal interface IMetadataSymbol 9 | { 10 | /// 11 | /// The metadata reader that was used to read up this metadata symbol. 12 | /// 13 | public MetadataReader MetadataReader { get; } 14 | 15 | /// 16 | /// The metadata assembly of this metadata symbol. 17 | /// 18 | public MetadataAssemblySymbol Assembly { get; } 19 | 20 | /// 21 | /// The metadata name used for referencing this symbol. 22 | /// 23 | public string MetadataName { get; } 24 | } 25 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Symbols/Metadata/MetadataPropertyAccessorSymbol.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection.Metadata; 2 | 3 | namespace Draco.Compiler.Internal.Symbols.Metadata; 4 | 5 | /// 6 | /// Represents an property accessor symbol loaded from metadata. 7 | /// 8 | internal sealed class MetadataPropertyAccessorSymbol( 9 | Symbol containingSymbol, 10 | MethodDefinition definition, 11 | PropertySymbol property) : MetadataMethodSymbol(containingSymbol, definition), IPropertyAccessorSymbol 12 | { 13 | public PropertySymbol Property { get; } = property; 14 | } 15 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Symbols/ReferenceTypeSymbol.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.Compiler.Internal.Symbols; 2 | 3 | /// 4 | /// Represents a reference type. 5 | /// 6 | internal sealed class ReferenceTypeSymbol(TypeSymbol elementType) : TypeSymbol 7 | { 8 | /// 9 | /// The element type that the reference references to. 10 | /// 11 | public TypeSymbol ElementType { get; } = elementType; 12 | 13 | public override bool IsValueType => true; 14 | 15 | public override string ToString() => $"ref {this.ElementType}"; 16 | } 17 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Symbols/Script/ScriptAutoPropertySymbol.cs: -------------------------------------------------------------------------------- 1 | using Draco.Compiler.Api.Syntax; 2 | using Draco.Compiler.Internal.Binding; 3 | using Draco.Compiler.Internal.Symbols.Source; 4 | using Draco.Compiler.Internal.Symbols.Syntax; 5 | 6 | namespace Draco.Compiler.Internal.Symbols.Script; 7 | 8 | /// 9 | /// A property defined inside a script. 10 | /// 11 | /// Properties are special in script context, as global properties (global variables) can be inferred from other statements, 12 | /// and their initialization intermixes with the rest of the script. 13 | /// 14 | internal sealed class ScriptAutoPropertySymbol( 15 | ScriptModuleSymbol containingSymbol, 16 | VariableDeclarationSyntax syntax) : SyntaxAutoPropertySymbol(containingSymbol, syntax), ISourceSymbol 17 | { 18 | public override TypeSymbol Type => this.type ??= new TypeVariable(1); 19 | private TypeSymbol? type; 20 | 21 | public override Api.Semantics.Visibility Visibility => Api.Semantics.Visibility.Public; 22 | 23 | public override void Bind(IBinderProvider binderProvider) => containingSymbol.Bind(binderProvider); 24 | } 25 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Symbols/Script/ScriptFieldSymbol.cs: -------------------------------------------------------------------------------- 1 | using Draco.Compiler.Api.Syntax; 2 | using Draco.Compiler.Internal.Binding; 3 | using Draco.Compiler.Internal.Symbols.Source; 4 | using Draco.Compiler.Internal.Symbols.Syntax; 5 | 6 | namespace Draco.Compiler.Internal.Symbols.Script; 7 | 8 | /// 9 | /// A field defined inside a script. 10 | /// 11 | /// Fields are special in script context, as global fields (global variables) can be inferred from other statements, 12 | /// and their initialization intermixes with the rest of the script. 13 | /// 14 | internal sealed class ScriptFieldSymbol( 15 | ScriptModuleSymbol containingSymbol, 16 | VariableDeclarationSyntax syntax) : SyntaxFieldSymbol(containingSymbol, syntax), ISourceSymbol 17 | { 18 | public override TypeSymbol Type => this.type ??= new TypeVariable(1); 19 | private TypeSymbol? type; 20 | 21 | public override Api.Semantics.Visibility Visibility => Api.Semantics.Visibility.Public; 22 | 23 | public override void Bind(IBinderProvider binderProvider) => containingSymbol.Bind(binderProvider); 24 | } 25 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Symbols/Script/ScriptFunctionSymbol.cs: -------------------------------------------------------------------------------- 1 | using Draco.Compiler.Api.Semantics; 2 | using Draco.Compiler.Api.Syntax; 3 | using Draco.Compiler.Internal.Binding; 4 | using Draco.Compiler.Internal.BoundTree; 5 | using Draco.Compiler.Internal.Symbols.Source; 6 | using Draco.Compiler.Internal.Symbols.Syntax; 7 | 8 | namespace Draco.Compiler.Internal.Symbols.Script; 9 | 10 | /// 11 | /// A function defined inside a script. 12 | /// 13 | internal sealed class ScriptFunctionSymbol( 14 | ScriptModuleSymbol containingSymbol, 15 | FunctionDeclarationSyntax syntax) : SyntaxFunctionSymbol(containingSymbol, syntax), ISourceSymbol 16 | { 17 | public override BoundStatement Body => 18 | ((ScriptModuleSymbol)this.ContainingSymbol).ScriptBindings.FunctionBodies[this.DeclaringSyntax]; 19 | public override Visibility Visibility => Visibility.Public; 20 | 21 | public override void Bind(IBinderProvider binderProvider) 22 | { 23 | this.BindAttributesIfNeeded(binderProvider); 24 | containingSymbol.Bind(binderProvider); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Symbols/Source/ISourceSymbol.cs: -------------------------------------------------------------------------------- 1 | using Draco.Compiler.Internal.Binding; 2 | 3 | namespace Draco.Compiler.Internal.Symbols.Source; 4 | 5 | /// 6 | /// An interface for all symbols defined in-source. 7 | /// 8 | internal interface ISourceSymbol 9 | { 10 | /// 11 | /// Enforced binding of the symbol. It does not recurse to bind members of the symbol. 12 | /// 13 | /// The provider to get binders from. 14 | public void Bind(IBinderProvider binderProvider); 15 | } 16 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Symbols/Source/SourceLabelSymbol.cs: -------------------------------------------------------------------------------- 1 | using Draco.Compiler.Api.Syntax; 2 | using Draco.Compiler.Internal.Binding; 3 | 4 | namespace Draco.Compiler.Internal.Symbols.Source; 5 | 6 | /// 7 | /// An in-source label definition. 8 | /// 9 | internal sealed class SourceLabelSymbol( 10 | Symbol containingSymbol, 11 | LabelDeclarationSyntax declarationSyntax) : LabelSymbol, ISourceSymbol 12 | { 13 | public override Symbol ContainingSymbol { get; } = containingSymbol; 14 | public override string Name => this.DeclaringSyntax.Name.Text; 15 | 16 | public override LabelDeclarationSyntax DeclaringSyntax { get; } = declarationSyntax; 17 | 18 | public void Bind(IBinderProvider binderProvider) { } 19 | } 20 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Symbols/Source/SourceTypeParameterSymbol.cs: -------------------------------------------------------------------------------- 1 | using Draco.Compiler.Api.Syntax; 2 | using Draco.Compiler.Internal.Binding; 3 | 4 | namespace Draco.Compiler.Internal.Symbols.Source; 5 | 6 | /// 7 | /// A generic type parameter defined in-source. 8 | /// 9 | internal sealed class SourceTypeParameterSymbol( 10 | Symbol containingSymbol, 11 | GenericParameterSyntax syntax) : TypeParameterSymbol, ISourceSymbol 12 | { 13 | public override Symbol ContainingSymbol { get; } = containingSymbol; 14 | public override string Name => this.DeclaringSyntax.Name.Text; 15 | 16 | public override GenericParameterSyntax DeclaringSyntax { get; } = syntax; 17 | 18 | public void Bind(IBinderProvider binderProvider) { } 19 | } 20 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Symbols/Synthetized/AutoProperty/AutoPropertyBackingFieldSymbol.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.Compiler.Internal.Symbols.Synthetized.AutoProperty; 2 | 3 | /// 4 | /// Auto-generated backing field for an auto-property. 5 | /// 6 | internal sealed class AutoPropertyBackingFieldSymbol( 7 | Symbol containingSymbol, 8 | PropertySymbol property) : FieldSymbol 9 | { 10 | public override Symbol ContainingSymbol { get; } = containingSymbol; 11 | 12 | public override TypeSymbol Type => this.Property.Type; 13 | public override bool IsStatic => this.Property.IsStatic; 14 | public override bool IsMutable => this.Property.Setter is not null; 15 | public override string Name => $"<{this.Property.Name}>_BackingField"; 16 | public override Api.Semantics.Visibility Visibility => Api.Semantics.Visibility.Private; 17 | public override bool IsSpecialName => true; 18 | 19 | /// 20 | /// The property this backing field is for. 21 | /// 22 | public PropertySymbol Property { get; } = property; 23 | } 24 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Symbols/Synthetized/NeverTypeSymbol.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.Compiler.Internal.Symbols.Synthetized; 2 | 3 | /// 4 | /// Represents the type of an unreachable piece of code, also known as the bottom-type. 5 | /// 6 | internal sealed class NeverTypeSymbol : TypeSymbol 7 | { 8 | /// 9 | /// A singleton instance. 10 | /// 11 | public static NeverTypeSymbol Instance { get; } = new(); 12 | 13 | private NeverTypeSymbol() 14 | { 15 | } 16 | 17 | public override string ToString() => ""; 18 | } 19 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Symbols/Synthetized/PrimitiveTypeSymbol.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Immutable; 2 | using Draco.Compiler.Internal.Symbols.Generic; 3 | 4 | namespace Draco.Compiler.Internal.Symbols.Synthetized; 5 | 6 | /// 7 | /// A built-in primitive. 8 | /// 9 | internal sealed class PrimitiveTypeSymbol(string name, bool isValueType) : TypeSymbol 10 | { 11 | public override string Name { get; } = name; 12 | public override bool IsValueType { get; } = isValueType; 13 | 14 | public override TypeSymbol GenericInstantiate(Symbol? containingSymbol, ImmutableArray arguments) => 15 | base.GenericInstantiate(containingSymbol, arguments); 16 | public override TypeSymbol GenericInstantiate(Symbol? containingSymbol, GenericContext context) => this; 17 | 18 | public override string ToString() => this.Name; 19 | } 20 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Symbols/Synthetized/SynthetizedAliasSymbol.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.Compiler.Internal.Symbols.Synthetized; 2 | 3 | /// 4 | /// An alias defined by the compiler. 5 | /// 6 | internal sealed class SynthetizedAliasSymbol(string name, Symbol substitution) : AliasSymbol 7 | { 8 | public override string MetadataName => this.Substitution.MetadataName; 9 | public override string Name => name; 10 | public override Symbol Substitution => substitution; 11 | public override Api.Semantics.Visibility Visibility => Api.Semantics.Visibility.Public; 12 | } 13 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Symbols/Synthetized/SynthetizedLabelSymbol.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.Compiler.Internal.Symbols.Synthetized; 2 | 3 | /// 4 | /// A label generated by the compiler. 5 | /// 6 | internal sealed class SynthetizedLabelSymbol(string name) : LabelSymbol 7 | { 8 | public override string Name { get; } = name; 9 | 10 | public SynthetizedLabelSymbol() 11 | : this(string.Empty) 12 | { 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Symbols/Synthetized/SynthetizedLocalSymbol.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.Compiler.Internal.Symbols.Synthetized; 2 | 3 | /// 4 | /// A local generated by the compiler. 5 | /// 6 | internal sealed class SynthetizedLocalSymbol(TypeSymbol type, bool isMutable) : LocalSymbol 7 | { 8 | public override TypeSymbol Type { get; } = type; 9 | public override bool IsMutable { get; } = isMutable; 10 | } 11 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Symbols/Synthetized/SynthetizedParameterSymbol.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.Compiler.Internal.Symbols.Synthetized; 2 | 3 | /// 4 | /// A parameter constructed by the compiler. 5 | /// 6 | internal sealed class SynthetizedParameterSymbol( 7 | FunctionSymbol containingSymbol, 8 | string name, 9 | TypeSymbol type) : ParameterSymbol 10 | { 11 | public override string Name { get; } = name; 12 | public override TypeSymbol Type { get; } = type; 13 | 14 | public override FunctionSymbol ContainingSymbol { get; } = containingSymbol; 15 | 16 | public SynthetizedParameterSymbol(FunctionSymbol containingSymbol, TypeSymbol type) 17 | : this(containingSymbol, string.Empty, type) 18 | { 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Symbols/Synthetized/SynthetizedTypeParameterSymbol.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.Compiler.Internal.Symbols.Synthetized; 2 | 3 | /// 4 | /// A type parameter synthetized by the compiler. 5 | /// 6 | internal sealed class SynthetizedTypeParameterSymbol( 7 | Symbol? containingSymbol, 8 | string name) : TypeParameterSymbol 9 | { 10 | public override Symbol? ContainingSymbol { get; } = containingSymbol; 11 | 12 | public override string Name { get; } = name; 13 | } 14 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Symbols/VariableSymbol.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.Compiler.Internal.Symbols; 2 | 3 | /// 4 | /// Any variable-like symbol. 5 | /// 6 | internal abstract partial class VariableSymbol : Symbol, ITypedSymbol 7 | { 8 | public abstract TypeSymbol Type { get; } 9 | 10 | /// 11 | /// True, if this variable is mutable. 12 | /// 13 | public abstract bool IsMutable { get; } 14 | } 15 | -------------------------------------------------------------------------------- /src/Draco.Compiler/Internal/Utilities/InterlockedUtils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Immutable; 3 | using System.Diagnostics.CodeAnalysis; 4 | using System.Threading; 5 | 6 | namespace Draco.Compiler.Internal.Utilities; 7 | 8 | /// 9 | /// Utility functions for atomic operations. 10 | /// 11 | [ExcludeFromCodeCoverage] 12 | internal static class InterlockedUtils 13 | { 14 | public static T? InitializeMaybeNull(ref T? field, Func factory) 15 | where T : class 16 | { 17 | if (field is null) Interlocked.CompareExchange(ref field, factory(), null); 18 | return field; 19 | } 20 | 21 | public static ImmutableArray InitializeDefault(ref ImmutableArray field, Func> factory) 22 | { 23 | if (field.IsDefault) ImmutableInterlocked.InterlockedInitialize(ref field, factory()); 24 | return field; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Draco.Coverage.Cli/Draco.Coverage.Cli.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/Draco.Coverage.Tasks/Draco.Coverage.Tasks.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | false 6 | disable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/Draco.Coverage.Toolset/build/Draco.Coverage.Toolset.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/Draco.Coverage.Toolset/build/Draco.Coverage.Toolset.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/Draco.Coverage/Draco.Coverage.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/Draco.Coverage/InstrumentationWeaverSettings.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.Coverage; 2 | 3 | /// 4 | /// Settings for the instrumentation weaver. 5 | /// 6 | public sealed class InstrumentationWeaverSettings 7 | { 8 | /// 9 | /// The default settings. 10 | /// 11 | public static InstrumentationWeaverSettings Default { get; } = new(); 12 | 13 | /// 14 | /// True, if the weaver should check for the ExcludeCoverage attribute. 15 | /// 16 | public bool CheckForExcludeCoverageAttribute { get; } 17 | 18 | /// 19 | /// True, if the weaver should check for the CompilerGenerated attribute. 20 | /// 21 | public bool CheckForCompilerGeneratedAttribute { get; } 22 | 23 | public InstrumentationWeaverSettings( 24 | bool checkForExcludeCoverageAttribute = true, 25 | bool checkForCompilerGeneratedAttribute = true) 26 | { 27 | this.CheckForExcludeCoverageAttribute = checkForExcludeCoverageAttribute; 28 | this.CheckForCompilerGeneratedAttribute = checkForCompilerGeneratedAttribute; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Draco.Coverage/Platform/BufferHandle.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.Coverage.Platform; 2 | 3 | internal readonly unsafe record struct BufferHandle( 4 | nint NativeHandle, 5 | nint Buffer, 6 | string Name); 7 | -------------------------------------------------------------------------------- /src/Draco.Dap/Adapter/Capabilities/IConfigurationSequence.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Draco.Dap.Attributes; 3 | using Draco.Dap.Model; 4 | 5 | namespace Draco.Dap.Adapter.Capabilities; 6 | 7 | public interface IConfigurationSequence 8 | { 9 | [Capability(nameof(Model.Capabilities.SupportsConfigurationDoneRequest))] 10 | public bool SupportsConfigurationDoneRequest => true; 11 | 12 | [Request("configurationDone")] 13 | public Task ConfigurationDoneAsync(ConfigurationDoneArguments args); 14 | } 15 | -------------------------------------------------------------------------------- /src/Draco.Dap/Adapter/Capabilities/IExceptionBreakpoint.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using Draco.Dap.Attributes; 4 | using Draco.Dap.Model; 5 | 6 | namespace Draco.Dap.Adapter.Capabilities; 7 | 8 | public interface IExceptionBreakpoint 9 | { 10 | [Capability(nameof(Model.Capabilities.ExceptionBreakpointFilters))] 11 | public IList ExceptionBreakpointFilters { get; } 12 | 13 | [Request("setExceptionBreakpoints", Mutating = true)] 14 | public Task SetExceptionBreakpointsAsync(SetExceptionBreakpointsArguments args); 15 | } 16 | -------------------------------------------------------------------------------- /src/Draco.Dap/Adapter/DebugClientProxy.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using Draco.JsonRpc; 3 | 4 | namespace Draco.Dap.Adapter; 5 | 6 | // NOTE: Not sealed since DispatchProxy generates a class derived from this at runtime 7 | internal class DebugClientProxy : JsonRpcClientProxy 8 | { 9 | protected override IJsonRpcMethodHandler CreateHandler(MethodInfo method) => 10 | DebugAdapterMethodHandler.Create(method, this); 11 | } 12 | -------------------------------------------------------------------------------- /src/Draco.Dap/Adapter/IDebugAdapterLifecycle.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Draco.Dap.Attributes; 3 | using Draco.Dap.Model; 4 | 5 | namespace Draco.Dap.Adapter; 6 | 7 | internal interface IDebugAdapterLifecycle 8 | { 9 | [Request("initialize")] 10 | public Task InitializeAsync(InitializeRequestArguments args); 11 | } 12 | -------------------------------------------------------------------------------- /src/Draco.Dap/Adapter/IDebugClient.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Draco.Dap.Attributes; 3 | using Draco.Dap.Model; 4 | 5 | namespace Draco.Dap.Adapter; 6 | 7 | /// 8 | /// An interface representing the debug client on the remote. 9 | /// 10 | public interface IDebugClient 11 | { 12 | [Event("initialized")] 13 | public Task Initialized(); 14 | 15 | [Event("output", Mutating = true)] 16 | public Task SendOutputAsync(OutputEvent args); 17 | 18 | [Event("process")] 19 | public Task ProcessStartedAsync(ProcessEvent args); 20 | 21 | [Event("breakpoint")] 22 | public Task UpdateBreakpointAsync(BreakpointEvent args); 23 | 24 | [Event("stopped")] 25 | public Task StoppedAsync(StoppedEvent args); 26 | 27 | [Event("exited")] 28 | public Task ProcessExitedAsync(ExitedEvent args); 29 | 30 | [Event("terminated")] 31 | public Task DebuggerTerminatedAsync(TerminatedEvent args); 32 | 33 | [Event("module")] 34 | public Task UpdateModuleAsync(ModuleEvent args); 35 | } 36 | -------------------------------------------------------------------------------- /src/Draco.Dap/Attributes/CapabilityAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Draco.Dap.Attributes; 4 | 5 | // NOTE: While currently almost all debug adapter capabilities are merely booleans, 6 | // so annotating the type would be enough, but there are already two exceptions: 7 | // - CompletionTriggerCharacters 8 | // - AdditionalModuleColumns 9 | // So for most cases, we'll just annotate a => true prop in the capability interfaces to avoid 10 | // starting to hack in this extra data. 11 | // If a capability potentially sets multiple properties, we just annotate all of the props with the 12 | // corresponding capability name. 13 | 14 | /// 15 | /// Annotates a capability property. 16 | /// 17 | [AttributeUsage(AttributeTargets.Property)] 18 | public sealed class CapabilityAttribute(string property) : Attribute 19 | { 20 | /// 21 | /// The capability's property name. 22 | /// 23 | public string Property { get; set; } = property; 24 | } 25 | -------------------------------------------------------------------------------- /src/Draco.Dap/Attributes/EventAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Draco.Dap.Attributes; 4 | 5 | /// 6 | /// Annotates a JSON-RPC event. 7 | /// 8 | [AttributeUsage(AttributeTargets.Method)] 9 | public sealed class EventAttribute(string method) : Attribute 10 | { 11 | /// 12 | /// The method being called. 13 | /// 14 | public string Method { get; set; } = method; 15 | 16 | /// 17 | /// Whether the event will mutate the debug adapter. 18 | /// 19 | public bool Mutating { get; set; } 20 | } 21 | -------------------------------------------------------------------------------- /src/Draco.Dap/Attributes/RequestAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Draco.Dap.Attributes; 4 | 5 | /// 6 | /// Annotates a JSON-RPC request. 7 | /// 8 | [AttributeUsage(AttributeTargets.Method)] 9 | public sealed class RequestAttribute(string method) : Attribute 10 | { 11 | /// 12 | /// The method being called. 13 | /// 14 | public string Method { get; set; } = method; 15 | 16 | /// 17 | /// Whether the request will mutate the debug adapter. 18 | /// 19 | public bool Mutating { get; set; } 20 | } 21 | -------------------------------------------------------------------------------- /src/Draco.Dap/Draco.Dap.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/Draco.Dap/Model/AttachRequestArguments.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Text.Json; 3 | using System.Text.Json.Serialization; 4 | 5 | namespace Draco.Dap.Model; 6 | 7 | // NOTE: Custom because of AttachAttributes 8 | /// 9 | /// Arguments for `launch` request. Additional attributes are implementation specific. 10 | /// 11 | public class AttachRequestArguments 12 | { 13 | /// 14 | /// Arbitrary data from the previous, restarted session. 15 | /// The data is sent as the `restart` attribute of the `terminated` event. 16 | /// The client should leave the data intact. 17 | /// 18 | [JsonPropertyName("__restart")] 19 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] 20 | public JsonElement? __Restart { get; set; } 21 | 22 | /// 23 | /// Implementation-specific attach attributes. 24 | /// 25 | [JsonExtensionData] 26 | public Dictionary? AttachAttributes { get; set; } 27 | } 28 | -------------------------------------------------------------------------------- /src/Draco.Dap/Model/DapModel.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/Draco.Dap/Model/EventMessage.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json; 2 | using System.Text.Json.Serialization; 3 | 4 | namespace Draco.Dap.Model; 5 | 6 | internal sealed class EventMessage 7 | { 8 | [JsonPropertyName("seq")] 9 | [JsonIgnore(Condition = JsonIgnoreCondition.Never)] 10 | public required int SequenceNumber { get; set; } 11 | 12 | [JsonPropertyName("type")] 13 | [JsonIgnore(Condition = JsonIgnoreCondition.Never)] 14 | public string Type => "event"; 15 | 16 | [JsonPropertyName("event")] 17 | [JsonIgnore(Condition = JsonIgnoreCondition.Never)] 18 | public required string Event { get; set; } 19 | 20 | [JsonPropertyName("body")] 21 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] 22 | public JsonElement? Body { get; set; } 23 | } 24 | -------------------------------------------------------------------------------- /src/Draco.Dap/Model/ModelExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | 3 | namespace Draco.Dap.Model; 4 | 5 | /// 6 | /// Extension functionality for models. 7 | /// 8 | public static class ModelExtensions 9 | { 10 | public static string? GetMessage(this ErrorResponse error) 11 | { 12 | if (error.Error is null) return null; 13 | 14 | var result = new StringBuilder(error.Error.Format); 15 | if (error.Error.Variables is not null) 16 | { 17 | foreach (var (name, value) in error.Error.Variables) 18 | { 19 | result.Replace($"{{{name}}}", value); 20 | } 21 | } 22 | return result.ToString(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Draco.Dap/Model/OneOf.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | -------------------------------------------------------------------------------- /src/Draco.Dap/Model/RequestMessage.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json; 2 | using System.Text.Json.Serialization; 3 | 4 | namespace Draco.Dap.Model; 5 | 6 | internal sealed class RequestMessage 7 | { 8 | [JsonPropertyName("seq")] 9 | [JsonIgnore(Condition = JsonIgnoreCondition.Never)] 10 | public required int SequenceNumber { get; set; } 11 | 12 | [JsonPropertyName("type")] 13 | [JsonIgnore(Condition = JsonIgnoreCondition.Never)] 14 | public string Type => "request"; 15 | 16 | [JsonPropertyName("command")] 17 | [JsonIgnore(Condition = JsonIgnoreCondition.Never)] 18 | public required string Command { get; set; } 19 | 20 | [JsonPropertyName("arguments")] 21 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] 22 | public JsonElement? Arguments { get; set; } 23 | } 24 | -------------------------------------------------------------------------------- /src/Draco.DebugAdapter/Capabilities/ConfigurationSequence.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Draco.Dap.Adapter.Capabilities; 3 | using Draco.Dap.Model; 4 | 5 | namespace Draco.DebugAdapter; 6 | 7 | internal sealed partial class DracoDebugAdapter : IConfigurationSequence 8 | { 9 | public Task ConfigurationDoneAsync(ConfigurationDoneArguments args) => 10 | Task.FromResult(new ConfigurationDoneResponse()); 11 | } 12 | -------------------------------------------------------------------------------- /src/Draco.DebugAdapter/Draco.DebugAdapter.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | 6 | 7 | true 8 | draco-debugadapter 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/Draco.DebugAdapter/PathEqualityComparer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics.CodeAnalysis; 4 | using System.IO; 5 | 6 | namespace Draco.DebugAdapter; 7 | 8 | internal sealed class PathEqualityComparer : EqualityComparer 9 | { 10 | public static PathEqualityComparer Instance { get; } = new(); 11 | 12 | private PathEqualityComparer() 13 | { 14 | } 15 | 16 | public override int GetHashCode([DisallowNull] string obj) => Path.GetFullPath(obj).GetHashCode(); 17 | public override bool Equals(string? x, string? y) 18 | { 19 | if (ReferenceEquals(x, y)) return true; 20 | if (x is null || y is null) return false; 21 | return Path.GetFullPath(x).Equals(Path.GetFullPath(y), StringComparison.InvariantCultureIgnoreCase); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Draco.Debugger.Tests/IoUtilsTests.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using Draco.Debugger.IO; 3 | using Xunit; 4 | 5 | namespace Draco.Debugger.Tests; 6 | 7 | public sealed class IoUtilsTests 8 | { 9 | [Fact] 10 | public async Task CapturedIOReadsReturnsZero() 11 | { 12 | var result = IoUtils.CaptureProcess(() => 13 | Process.Start(new ProcessStartInfo 14 | { 15 | FileName = "dotnet" 16 | }), out var handles); 17 | var reader = new StreamReader(handles.StandardOutputReader); 18 | var buffer = new char[1024]; 19 | var amount = await reader.ReadAsync(buffer); 20 | Assert.True(amount > 0); 21 | var str = new string(buffer, 0, amount); 22 | var emptyRead = await reader.ReadAsync(buffer); 23 | Assert.Equal(0, emptyRead); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Draco.Debugger.Tui/Draco.Debugger.Tui.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/Draco.Debugger.Tui/SourceFileListDataSource.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using Terminal.Gui; 5 | 6 | namespace Draco.Debugger.Tui; 7 | 8 | internal sealed class SourceFileListDataSource(IReadOnlyList sourceFiles) : IListDataSource 9 | { 10 | public int Count => this.sourceFiles.Count; 11 | public int Length => this.sourceFiles.Count; 12 | 13 | private readonly List sourceFiles = [.. sourceFiles]; 14 | 15 | public bool IsMarked(int item) => throw new NotSupportedException(); 16 | public void SetMark(int item, bool value) => throw new NotSupportedException(); 17 | public void Render(ListView container, ConsoleDriver driver, bool selected, int item, int col, int line, int width, int start = 0) 18 | { 19 | var selectedFile = this.sourceFiles[item]; 20 | var fileName = selectedFile.Uri.LocalPath; 21 | driver.AddStr(fileName); 22 | } 23 | public IList ToList() => this.sourceFiles; 24 | public int IndexOf(SourceFile sourceFile) => this.sourceFiles.IndexOf(sourceFile); 25 | } 26 | -------------------------------------------------------------------------------- /src/Draco.Debugger/Breakpoints/EntryPointBreakpoint.cs: -------------------------------------------------------------------------------- 1 | using ClrDebug; 2 | 3 | namespace Draco.Debugger.Breakpoints; 4 | 5 | internal sealed class EntryPointBreakpoint( 6 | SessionCache sessionCache, 7 | CorDebugFunctionBreakpoint corDebugBreakpoint) : MethodBreakpoint(sessionCache, corDebugBreakpoint) 8 | { 9 | public override bool IsEntryPoint => true; 10 | } 11 | -------------------------------------------------------------------------------- /src/Draco.Debugger/Breakpoints/MethodBreakpoint.cs: -------------------------------------------------------------------------------- 1 | using ClrDebug; 2 | 3 | namespace Draco.Debugger.Breakpoints; 4 | 5 | // NOTE: Not sealed, entry-point breakpoint reuses this 6 | internal class MethodBreakpoint : Breakpoint 7 | { 8 | internal override CorDebugFunctionBreakpoint CorDebugBreakpoint { get; } 9 | public override Method Method => this.SessionCache.GetMethod(this.CorDebugBreakpoint.Function); 10 | public override SourceRange? Range => this.Method.GetSourceRangeForIlOffset(this.CorDebugBreakpoint.Offset); 11 | 12 | public MethodBreakpoint(SessionCache sessionCache, CorDebugFunctionBreakpoint corDebugBreakpoint) 13 | : base(sessionCache) 14 | { 15 | this.CorDebugBreakpoint = corDebugBreakpoint; 16 | this.Method.MutableBreakpoints.Add(this); 17 | } 18 | 19 | public override void Remove() 20 | { 21 | this.Method.MutableBreakpoints.Remove(this); 22 | base.Remove(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Draco.Debugger/Draco.Debugger.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/Draco.Debugger/Events/OnBreakpointEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Draco.Debugger.Breakpoints; 3 | 4 | namespace Draco.Debugger.Events; 5 | 6 | /// 7 | /// The event arguments for the event when a breakpoint is hit. 8 | /// 9 | public sealed class OnBreakpointEventArgs : EventArgs 10 | { 11 | /// 12 | /// The thread that was stopped. 13 | /// 14 | public required Thread Thread { get; init; } 15 | 16 | /// 17 | /// The breakpoint we stopped at. 18 | /// 19 | public required Breakpoint Breakpoint { get; init; } 20 | } 21 | -------------------------------------------------------------------------------- /src/Draco.Debugger/Events/OnModuleEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Draco.Debugger.Events; 4 | 5 | public sealed class OnModuleEventArgs : EventArgs 6 | { 7 | /// 8 | /// The module that was loaded/unloaded. 9 | /// 10 | public required Module Module { get; init; } 11 | } 12 | -------------------------------------------------------------------------------- /src/Draco.Debugger/Events/OnStepEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Draco.Debugger.Events; 4 | 5 | /// 6 | /// The event arguments for the event when a step is complete. 7 | /// 8 | public sealed class OnStepEventArgs : EventArgs 9 | { 10 | /// 11 | /// The thread that was stopped. 12 | /// 13 | public required Thread Thread { get; init; } 14 | 15 | /// 16 | /// The method this step happened in. 17 | /// 18 | public Method? Method { get; init; } 19 | 20 | /// 21 | /// The range of the stepped statement. 22 | /// 23 | public SourceRange? Range { get; init; } 24 | 25 | /// 26 | /// The source file where the step landed. 27 | /// 28 | public SourceFile? SourceFile => this.Method?.SourceFile; 29 | } 30 | -------------------------------------------------------------------------------- /src/Draco.Debugger/IO/IoHandles.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Draco.Debugger.IO; 4 | 5 | /// 6 | /// A triplet of all STDIO handles for a process. 7 | /// 8 | /// The standard input handle. 9 | /// The standard output handle. 10 | /// The standard error handle. 11 | internal readonly record struct IoHandles( 12 | IntPtr StandardInput, 13 | IntPtr StandardOutput, 14 | IntPtr StandardError); 15 | -------------------------------------------------------------------------------- /src/Draco.Debugger/IO/RemoteIoHandles.cs: -------------------------------------------------------------------------------- 1 | using System.IO.Pipes; 2 | 3 | namespace Draco.Debugger.IO; 4 | 5 | /// 6 | /// A triplet of remote STDIO pipes that can be used to read from output handles and write to the input handle 7 | /// of another process. 8 | /// 9 | /// The input writer for the remote STDIN. 10 | /// The output reader for the remote STDOUT. 11 | /// The output reader for the remote STDERR. 12 | internal readonly record struct RemoteIoHandles( 13 | PipeStream StandardInputWriter, 14 | PipeStream StandardOutputReader, 15 | PipeStream StandardErrorReader); 16 | -------------------------------------------------------------------------------- /src/Draco.Debugger/PeUtils.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection.Metadata; 2 | using System.Reflection.Metadata.Ecma335; 3 | using System.Reflection.PortableExecutable; 4 | 5 | namespace Draco.Debugger; 6 | 7 | /// 8 | /// Utilities for PE files. 9 | /// 10 | internal static class PeUtils 11 | { 12 | /// 13 | /// Retrieves the entry point handle from the given PE file reader. 14 | /// 15 | /// The reader for the PE file. 16 | /// The of the entry point. Can be a nil handle, 17 | /// if the PE does not have a COR header or the executable has a native entry point. 18 | public static MethodDefinitionHandle GetEntryPoint(this PEReader reader) 19 | { 20 | var corHeader = reader.PEHeaders.CorHeader; 21 | if (corHeader is null) return default; 22 | if (corHeader.Flags.HasFlag(CorFlags.NativeEntryPoint)) return default; 23 | return MetadataTokens.MethodDefinitionHandle(corHeader.EntryPointTokenOrRelativeVirtualAddress); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Draco.Debugger/Platform/IPlatformMethods.cs: -------------------------------------------------------------------------------- 1 | using Draco.Debugger.IO; 2 | 3 | namespace Draco.Debugger.Platform; 4 | 5 | /// 6 | /// Platform abstractions for the different supported OSes. 7 | /// 8 | internal interface IPlatformMethods 9 | { 10 | /// 11 | /// Gets the standard IO handles of the current process. 12 | /// 13 | /// 14 | public IoHandles GetStdioHandles(); 15 | 16 | /// 17 | /// Sets the standard IO handles of the current process. 18 | /// 19 | /// 20 | public void SetStdioHandles(IoHandles handles); 21 | } 22 | -------------------------------------------------------------------------------- /src/Draco.Debugger/SequencePointExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection.Metadata; 2 | 3 | namespace Draco.Debugger; 4 | 5 | internal static class SequencePointExtensions 6 | { 7 | public static SourcePosition GetStartPosition(this SequencePoint sequencePoint) => 8 | new(Line: sequencePoint.StartLine, Column: sequencePoint.StartColumn); 9 | 10 | public static SourcePosition GetEndPosition(this SequencePoint sequencePoint) => 11 | new(Line: sequencePoint.EndLine, Column: sequencePoint.EndColumn); 12 | 13 | public static bool Contains(this SequencePoint sequencePoint, SourcePosition position) 14 | { 15 | var start = sequencePoint.GetStartPosition(); 16 | var end = sequencePoint.GetEndPosition(); 17 | return start <= position && position <= end; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Draco.Debugger/SourcePosition.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Draco.Debugger; 4 | 5 | /// 6 | /// Represents a position in source code. 7 | /// 8 | /// The 0-based line index. 9 | /// The 0-based column index. 10 | public readonly record struct SourcePosition(int Line, int Column) : IComparable 11 | { 12 | public int CompareTo(SourcePosition other) 13 | { 14 | var cmp = this.Line.CompareTo(other.Line); 15 | return cmp == 0 16 | ? this.Column.CompareTo(other.Column) 17 | : cmp; 18 | } 19 | 20 | public static bool operator <(SourcePosition left, SourcePosition right) => left.CompareTo(right) < 0; 21 | public static bool operator <=(SourcePosition left, SourcePosition right) => left.CompareTo(right) <= 0; 22 | public static bool operator >(SourcePosition left, SourcePosition right) => left.CompareTo(right) > 0; 23 | public static bool operator >=(SourcePosition left, SourcePosition right) => left.CompareTo(right) >= 0; 24 | } 25 | -------------------------------------------------------------------------------- /src/Draco.Debugger/SourceRange.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.Debugger; 2 | 3 | /// 4 | /// Represents a range of source code. 5 | /// 6 | /// The inclusive start position. 7 | /// The exclusive end position. 8 | public readonly record struct SourceRange(SourcePosition Start, SourcePosition End) 9 | { 10 | public SourceRange(int startLine, int startColumn, int endLine, int endColumn) 11 | : this( 12 | new SourcePosition(Line: startLine, Column: startColumn), 13 | new SourcePosition(Line: endLine, Column: endColumn)) 14 | { 15 | } 16 | 17 | /// 18 | /// Checks if the given position is within this range. 19 | /// 20 | /// The position to check. 21 | /// True, if this range contains . 22 | public bool Contains(SourcePosition position) => this.Start <= position && position < this.End; 23 | } 24 | -------------------------------------------------------------------------------- /src/Draco.Examples.Tests/Draco.Examples.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | enable 5 | false 6 | true 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | PreserveNewest 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/Draco.Examples.Tests/TestPriorityAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.Examples.Tests; 2 | 3 | [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] 4 | public sealed class TestPriorityAttribute(int priority) : Attribute 5 | { 6 | public int Priority => priority; 7 | } 8 | -------------------------------------------------------------------------------- /src/Draco.Extension.VsCode/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | out 3 | dist 4 | # We copy it from the original source 5 | syntaxes/draco.tmLanguage.json 6 | *.vsix 7 | -------------------------------------------------------------------------------- /src/Draco.Extension.VsCode/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | // A launch configuration that launches the extension inside a new window 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | { 6 | "version": "0.2.0", 7 | "configurations": [ 8 | { 9 | "name": "Extension", 10 | "type": "extensionHost", 11 | "request": "launch", 12 | "args": [ 13 | "--extensionDevelopmentPath=${workspaceFolder}" 14 | ], 15 | "outFiles": [ 16 | "${workspaceFolder}/dist/**/*.js" 17 | ], 18 | "preLaunchTask": "${defaultBuildTask}" 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /src/Draco.Extension.VsCode/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | // See https://go.microsoft.com/fwlink/?LinkId=733558 2 | // for the documentation about the tasks.json format 3 | { 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "type": "npm", 8 | "script": "watch", 9 | "problemMatcher": "$ts-webpack-watch", 10 | "isBackground": true, 11 | "presentation": { 12 | "reveal": "never", 13 | "group": "watchers" 14 | }, 15 | "group": { 16 | "kind": "build", 17 | "isDefault": true 18 | } 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /src/Draco.Extension.VsCode/.vscodeignore: -------------------------------------------------------------------------------- 1 | .vscode/** 2 | .vscode-test/** 3 | out/** 4 | node_modules/** 5 | src/** 6 | .gitignore 7 | .yarnrc 8 | webpack.config.js 9 | **/tsconfig.json 10 | **/.eslintrc.json 11 | **/*.map 12 | **/*.ts 13 | -------------------------------------------------------------------------------- /src/Draco.Extension.VsCode/draco-language-configuration.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": { 3 | // symbol used for single line comment. Remove this entry if your language does not support line comments 4 | "lineComment": "//" 5 | }, 6 | // symbols used as brackets 7 | "brackets": [ 8 | ["{", "}"], 9 | ["[", "]"], 10 | ["(", ")"] 11 | ], 12 | // symbols that are auto closed when typing 13 | "autoClosingPairs": [ 14 | ["{", "}"], 15 | ["[", "]"], 16 | ["(", ")"], 17 | ["\"", "\""], 18 | ["'", "'"] 19 | ], 20 | // symbols that can be used to surround a selection 21 | "surroundingPairs": [ 22 | ["{", "}"], 23 | ["[", "]"], 24 | ["(", ")"], 25 | ["\"", "\""], 26 | ["'", "'"] 27 | ] 28 | } -------------------------------------------------------------------------------- /src/Draco.Extension.VsCode/msbuild-language-configuration.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": { 3 | "lineComment": "", 4 | "blockComment": [""] 5 | }, 6 | "brackets": [ 7 | ["<", ">"], 8 | ["(", ")"], 9 | ["$(", ")"], 10 | ["@(", ")"], 11 | ["%(", ")"] 12 | ], 13 | "autoClosingPairs": [ 14 | ["<", ">"], 15 | ["'", "'"], 16 | ["\"", "\""] 17 | ], 18 | "surroundingPairs": [ 19 | ["<", ">"], 20 | ["'", "'"], 21 | ["\"", "\""] 22 | ] 23 | } -------------------------------------------------------------------------------- /src/Draco.Extension.VsCode/resources/extension-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Draco-lang/Compiler/57787f7ecef1a100e3496ba433950c84fcaed602/src/Draco.Extension.VsCode/resources/extension-icon.png -------------------------------------------------------------------------------- /src/Draco.Extension.VsCode/src/settings.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Settings handling. 3 | */ 4 | 5 | import { ConfigurationTarget, workspace } from "vscode"; 6 | 7 | /** 8 | * Writes a useful set of default settings. 9 | * @param target The @see ConfigurationTarget to write the defaults to. 10 | * @returns The promise that finishes, when all settings are updated. 11 | */ 12 | export function updateWithDefaultSettings(target: ConfigurationTarget): Promise { 13 | const settingsToInclude = [ 14 | 'dotnetCommand', 15 | 'sdkVersion', 16 | ]; 17 | const config = workspace.getConfiguration('draco'); 18 | return Promise.all(settingsToInclude.map(setting => 19 | config.update(setting, config.get(setting), target))); 20 | } 21 | -------------------------------------------------------------------------------- /src/Draco.Extension.VsCode/syntaxes/msbuild-draco.tmLanguage.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "MSBuild-Draco", 3 | "scopeName": "text.xml.msbuild-draco", 4 | "patterns": [ 5 | { 6 | "include": "text.xml" 7 | } 8 | ] 9 | } -------------------------------------------------------------------------------- /src/Draco.Extension.VsCode/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "ES2020", 5 | "outDir": "out", 6 | "lib": [ 7 | "ES2020" 8 | ], 9 | "sourceMap": true, 10 | "rootDir": "src", 11 | "strict": true, /* enable all strict type-checking options */ 12 | "noImplicitAny": true, 13 | /* Additional Checks */ 14 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 15 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 16 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Draco.Fuzzing.Tui/Addons/SeedFooterAddon.cs: -------------------------------------------------------------------------------- 1 | using Terminal.Gui; 2 | 3 | namespace Draco.Fuzzing.Tui.Addons; 4 | 5 | /// 6 | /// A simple addon to display the current random seed in the footer. 7 | /// 8 | public sealed class SeedFooterAddon : FuzzerAddon 9 | { 10 | public override StatusItem CreateStatusItem() => 11 | new(Key.Null, $"Seed: {this.Fuzzer.Settings.Seed}", () => { }); 12 | } 13 | -------------------------------------------------------------------------------- /src/Draco.Fuzzing.Tui/Draco.Fuzzing.Tui.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/Draco.Fuzzing.Tui/IFuzzerApplication.cs: -------------------------------------------------------------------------------- 1 | using Draco.Fuzzing.Tracing; 2 | 3 | namespace Draco.Fuzzing.Tui; 4 | 5 | /// 6 | /// The toplevel application that can have addons registered. 7 | /// 8 | public interface IFuzzerApplication 9 | { 10 | /// 11 | /// The fuzzer being visualized. 12 | /// 13 | public IFuzzer Fuzzer { get; } 14 | 15 | /// 16 | /// The tracer for the fuzzer. 17 | /// 18 | public EventTracer Tracer { get; } 19 | 20 | /// 21 | /// Requires the existence of an addon already registered. 22 | /// 23 | /// The type of the addon. 24 | /// The name of the addon. 25 | /// The name of the component requiring the addon for identification. 26 | /// The retrieved addon. 27 | public TAddon RequireAddon(string name, string by); 28 | } 29 | -------------------------------------------------------------------------------- /src/Draco.Fuzzing/Draco.Fuzzing.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/Draco.JsonRpc/Draco.JsonRpc.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | enable 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/Draco.JsonRpc/IJsonRpcClient.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.JsonRpc; 2 | 3 | /// 4 | /// The interface all JSON-RPC clients must implement. 5 | /// 6 | internal interface IJsonRpcClient 7 | { 8 | /// 9 | /// The connection. 10 | /// 11 | public IJsonRpcConnection Connection { get; } 12 | } 13 | -------------------------------------------------------------------------------- /src/Draco.LanguageServer/Capabilities/Configuration.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Draco.Lsp.Model; 3 | using Draco.Lsp.Server.Workspace; 4 | 5 | namespace Draco.LanguageServer; 6 | 7 | internal sealed partial class DracoLanguageServer : IDidChangeConfiguration 8 | { 9 | public async Task DidChangeConfigurationAsync(DidChangeConfigurationParams param) 10 | { 11 | await this.configurationRepository.UpdateConfigurationAsync(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Draco.LanguageServer/Capabilities/DidDeleteFiles.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Draco.Lsp.Model; 3 | using Draco.Lsp.Server.Workspace; 4 | 5 | namespace Draco.LanguageServer; 6 | 7 | internal partial class DracoLanguageServer : IDidDeleteFiles 8 | { 9 | public FileOperationRegistrationOptions DidDeleteFileRegistrationOptions => new() 10 | { 11 | Filters = 12 | [ 13 | new() 14 | { 15 | Pattern = new() 16 | { 17 | Glob = this.DocumentSelector[0].Pattern! 18 | } 19 | } 20 | ] 21 | }; 22 | 23 | public async Task DidDeleteFilesAsync(DeleteFilesParams param) 24 | { 25 | foreach (var file in param.Files) 26 | { 27 | await this.DeleteDocument(DocumentUri.From(file.Uri)); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Draco.LanguageServer/Configurations/InlayHintsConfiguration.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.LanguageServer.Configurations; 2 | 3 | internal sealed class InlayHintsConfiguration 4 | { 5 | public bool ParameterNames { get; set; } 6 | public bool VariableTypes { get; set; } 7 | public bool GenericArguments { get; set; } 8 | } 9 | -------------------------------------------------------------------------------- /src/Draco.LanguageServer/DracoConfigurationRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Draco.LanguageServer.Configurations; 3 | using Draco.Lsp.Model; 4 | using Draco.Lsp.Server; 5 | 6 | namespace Draco.LanguageServer; 7 | 8 | internal sealed class DracoConfigurationRepository(ILanguageClient client) 9 | { 10 | public InlayHintsConfiguration InlayHints { get; set; } = new(); 11 | 12 | public async Task UpdateConfigurationAsync() 13 | { 14 | var cfg = await client.GetConfigurationAsync( 15 | new ConfigurationItem() 16 | { 17 | Section = "draco.inlayHints", 18 | }); 19 | 20 | this.InlayHints.ParameterNames = cfg[0].GetProperty("parameterNames"u8).GetBoolean(); 21 | this.InlayHints.VariableTypes = cfg[0].GetProperty("variableTypes"u8).GetBoolean(); 22 | this.InlayHints.GenericArguments = cfg[0].GetProperty("genericArguments"u8).GetBoolean(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Draco.Lsp/Attributes/ClientCapabilityAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Draco.Lsp.Attributes; 4 | 5 | /// 6 | /// Annotates a server capability interface with the corresponding client capability. 7 | /// 8 | [AttributeUsage(AttributeTargets.Interface)] 9 | public sealed class ClientCapabilityAttribute(string path) : Attribute 10 | { 11 | /// 12 | /// The capability property path. 13 | /// 14 | public string Path { get; set; } = path; 15 | } 16 | -------------------------------------------------------------------------------- /src/Draco.Lsp/Attributes/NotificationAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Draco.Lsp.Attributes; 4 | 5 | /// 6 | /// Annotates a JSON-RPC notification. 7 | /// 8 | [AttributeUsage(AttributeTargets.Method)] 9 | public sealed class NotificationAttribute(string method) : Attribute 10 | { 11 | /// 12 | /// The method being called. 13 | /// 14 | public string Method { get; set; } = method; 15 | 16 | /// 17 | /// Whether the notification will mutate the workspace. 18 | /// 19 | public bool Mutating { get; set; } 20 | } 21 | -------------------------------------------------------------------------------- /src/Draco.Lsp/Attributes/RegistrationOptionsAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Draco.Lsp.Attributes; 4 | 5 | /// 6 | /// Annotates registration options within the capability interfaces. 7 | /// 8 | [AttributeUsage(AttributeTargets.Property)] 9 | public sealed class RegistrationOptionsAttribute(string method) : Attribute 10 | { 11 | /// 12 | /// The method to register onto. 13 | /// 14 | public string Method { get; set; } = method; 15 | } 16 | -------------------------------------------------------------------------------- /src/Draco.Lsp/Attributes/RequestAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Draco.Lsp.Attributes; 4 | 5 | /// 6 | /// Annotates a JSON-RPC request. 7 | /// 8 | [AttributeUsage(AttributeTargets.Method)] 9 | public sealed class RequestAttribute(string method) : Attribute 10 | { 11 | /// 12 | /// The method being called. 13 | /// 14 | public string Method { get; set; } = method; 15 | 16 | /// 17 | /// Whether the request will mutate the workspace. 18 | /// 19 | public bool Mutating { get; set; } 20 | } 21 | -------------------------------------------------------------------------------- /src/Draco.Lsp/Attributes/ServerCapabilityAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Draco.Lsp.Attributes; 4 | 5 | /// 6 | /// Annotates a server capability property. 7 | /// 8 | [AttributeUsage(AttributeTargets.Property)] 9 | public sealed class ServerCapabilityAttribute(string property) : Attribute 10 | { 11 | /// 12 | /// The capability's property name. 13 | /// 14 | public string Property { get; set; } = property; 15 | } 16 | -------------------------------------------------------------------------------- /src/Draco.Lsp/Draco.Lsp.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/Draco.Lsp/Model/DocumentUri.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.Json.Serialization; 3 | using Draco.Lsp.Serialization; 4 | 5 | namespace Draco.Lsp.Model; 6 | 7 | [JsonConverter(typeof(DocumentUriConverter))] 8 | public readonly record struct DocumentUri : IEquatable 9 | { 10 | public static DocumentUri From(Uri uri) => new(uri); 11 | 12 | private readonly Uri uri; 13 | 14 | private DocumentUri(Uri uri) 15 | { 16 | this.uri = uri; 17 | } 18 | 19 | public DocumentUri(string path) 20 | : this(new Uri(path)) 21 | { 22 | } 23 | 24 | public Uri ToUri() => this.uri; 25 | 26 | public override string ToString() => this.uri.ToString(); 27 | } 28 | -------------------------------------------------------------------------------- /src/Draco.Lsp/Model/FileDelete.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace Draco.Lsp.Model; 4 | 5 | /// 6 | /// Represents information on a file/folder delete. 7 | /// 8 | /// @since 3.16.0 9 | /// 10 | public sealed class FileDelete 11 | { 12 | /// 13 | /// A file:// URI for the location of the file/folder being deleted. 14 | /// 15 | [JsonPropertyName("uri")] 16 | [JsonIgnore(Condition = JsonIgnoreCondition.Never)] 17 | [JsonRequired] 18 | public required System.Uri Uri { get; set; } 19 | } 20 | -------------------------------------------------------------------------------- /src/Draco.Lsp/Model/LspModel.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/Draco.Lsp/Model/NotificationMessage.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json; 2 | using System.Text.Json.Serialization; 3 | 4 | namespace Draco.Lsp.Model; 5 | 6 | internal sealed class NotificationMessage 7 | { 8 | [JsonPropertyName("jsonrpc")] 9 | [JsonIgnore(Condition = JsonIgnoreCondition.Never)] 10 | public required string Jsonrpc { get; set; } 11 | 12 | [JsonPropertyName("method")] 13 | [JsonIgnore(Condition = JsonIgnoreCondition.Never)] 14 | public required string Method { get; set; } 15 | 16 | [JsonPropertyName("params")] 17 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] 18 | public JsonElement? Params { get; set; } 19 | } 20 | -------------------------------------------------------------------------------- /src/Draco.Lsp/Model/OneOf.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | -------------------------------------------------------------------------------- /src/Draco.Lsp/Model/RequestMessage.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json; 2 | using System.Text.Json.Serialization; 3 | 4 | namespace Draco.Lsp.Model; 5 | 6 | internal sealed class RequestMessage 7 | { 8 | [JsonPropertyName("jsonrpc")] 9 | [JsonIgnore(Condition = JsonIgnoreCondition.Never)] 10 | public required string Jsonrpc { get; set; } 11 | 12 | [JsonPropertyName("id")] 13 | [JsonIgnore(Condition = JsonIgnoreCondition.Never)] 14 | public required OneOf Id { get; set; } 15 | 16 | [JsonPropertyName("method")] 17 | [JsonIgnore(Condition = JsonIgnoreCondition.Never)] 18 | public required string Method { get; set; } 19 | 20 | [JsonPropertyName("params")] 21 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] 22 | public JsonElement? Params { get; set; } 23 | } 24 | -------------------------------------------------------------------------------- /src/Draco.Lsp/Model/ResponseError.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json; 2 | using System.Text.Json.Serialization; 3 | 4 | namespace Draco.Lsp.Model; 5 | 6 | internal sealed class ResponseError 7 | { 8 | [JsonPropertyName("code")] 9 | [JsonIgnore(Condition = JsonIgnoreCondition.Never)] 10 | public required int Code { get; set; } 11 | 12 | [JsonPropertyName("message")] 13 | [JsonIgnore(Condition = JsonIgnoreCondition.Never)] 14 | public required string Message { get; set; } 15 | 16 | [JsonPropertyName("data")] 17 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] 18 | public JsonElement? Data { get; set; } 19 | } 20 | -------------------------------------------------------------------------------- /src/Draco.Lsp/Model/ResponseMessage.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json; 2 | using System.Text.Json.Serialization; 3 | 4 | namespace Draco.Lsp.Model; 5 | 6 | internal sealed class ResponseMessage 7 | { 8 | [JsonPropertyName("jsonrpc")] 9 | [JsonIgnore(Condition = JsonIgnoreCondition.Never)] 10 | public required string Jsonrpc { get; set; } 11 | 12 | [JsonPropertyName("id")] 13 | [JsonIgnore(Condition = JsonIgnoreCondition.Never)] 14 | public required OneOf? Id { get; set; } 15 | 16 | [JsonPropertyName("result")] 17 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] 18 | public JsonElement Result { get; set; } 19 | 20 | [JsonPropertyName("error")] 21 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] 22 | public ResponseError? Error { get; set; } 23 | } 24 | -------------------------------------------------------------------------------- /src/Draco.Lsp/Serialization/DocumentUriConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.Json; 3 | using System.Text.Json.Serialization; 4 | using Draco.Lsp.Model; 5 | 6 | namespace Draco.Lsp.Serialization; 7 | 8 | /// 9 | /// Converter for . 10 | /// 11 | internal sealed class DocumentUriConverter : JsonConverter 12 | { 13 | public override DocumentUri Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) 14 | => new(Uri.UnescapeDataString(reader.GetString() ?? string.Empty)); 15 | 16 | public override DocumentUri ReadAsPropertyName(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) 17 | => new(Uri.UnescapeDataString(reader.GetString() ?? string.Empty)); 18 | 19 | public override void Write(Utf8JsonWriter writer, DocumentUri value, JsonSerializerOptions options) 20 | => writer.WriteStringValue(value.ToString()); 21 | 22 | public override void WriteAsPropertyName(Utf8JsonWriter writer, DocumentUri value, JsonSerializerOptions options) 23 | => writer.WritePropertyName(value.ToString()); 24 | } 25 | -------------------------------------------------------------------------------- /src/Draco.Lsp/Serialization/UriConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.Json; 3 | using System.Text.Json.Serialization; 4 | 5 | namespace Draco.Lsp.Serialization; 6 | 7 | /// 8 | /// Converter for . 9 | /// 10 | internal sealed class UriConverter : JsonConverter 11 | { 12 | public override Uri Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) 13 | => new(Uri.UnescapeDataString(reader.GetString() ?? string.Empty)); 14 | 15 | public override Uri ReadAsPropertyName(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) 16 | => new(Uri.UnescapeDataString(reader.GetString() ?? string.Empty)); 17 | 18 | public override void Write(Utf8JsonWriter writer, Uri value, JsonSerializerOptions options) 19 | => writer.WriteStringValue(value.ToString()); 20 | 21 | public override void WriteAsPropertyName(Utf8JsonWriter writer, Uri value, JsonSerializerOptions options) 22 | => writer.WritePropertyName(value.ToString()); 23 | } 24 | -------------------------------------------------------------------------------- /src/Draco.Lsp/Server/ILanguageClient.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Text.Json; 3 | using System.Threading.Tasks; 4 | using Draco.Lsp.Attributes; 5 | using Draco.Lsp.Model; 6 | 7 | namespace Draco.Lsp.Server; 8 | 9 | /// 10 | /// An interface representing the language client on the remote. 11 | /// 12 | public interface ILanguageClient 13 | { 14 | // Language features 15 | 16 | [Notification("textDocument/publishDiagnostics")] 17 | public Task PublishDiagnosticsAsync(PublishDiagnosticsParams param); 18 | 19 | // Workspace features 20 | 21 | [Request("workspace/configuration")] 22 | public Task> GetConfigurationAsync(ConfigurationParams param); 23 | 24 | // Window features 25 | 26 | [Notification("window/showMessage")] 27 | public Task ShowMessageAsync(ShowMessageParams param); 28 | 29 | [Notification("window/logMessage")] 30 | public Task LogMessageAsync(LogMessageParams param); 31 | } 32 | -------------------------------------------------------------------------------- /src/Draco.Lsp/Server/ILanguageServer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using Draco.Lsp.Attributes; 4 | using Draco.Lsp.Model; 5 | 6 | namespace Draco.Lsp.Server; 7 | 8 | /// 9 | /// The interface that language servers need to implement. 10 | /// 11 | public interface ILanguageServer : IDisposable 12 | { 13 | /// 14 | /// General server information. 15 | /// 16 | public InitializeResult.ServerInfoResult? Info { get; } 17 | 18 | // NOTE: This is handled by the lifecycle manager, so it's not annotated 19 | // The lifecycle manager will dynamically register capabilities here, 20 | // then invokes these methods 21 | public Task InitializeAsync(InitializeParams param); 22 | 23 | public Task InitializedAsync(InitializedParams param); 24 | 25 | [Request("shutdown")] 26 | public Task ShutdownAsync(); 27 | } 28 | -------------------------------------------------------------------------------- /src/Draco.Lsp/Server/ILanguageServerLifecycle.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Draco.Lsp.Attributes; 3 | using Draco.Lsp.Model; 4 | 5 | namespace Draco.Lsp.Server; 6 | 7 | internal interface ILanguageServerLifecycle 8 | { 9 | [Request("initialize")] 10 | public Task InitializeAsync(InitializeParams param); 11 | 12 | [Notification("initialized")] 13 | public Task InitializedAsync(InitializedParams param); 14 | 15 | [Notification("exit")] 16 | public Task ExitAsync(); 17 | } 18 | -------------------------------------------------------------------------------- /src/Draco.Lsp/Server/Language/ICodeAction.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | using Draco.Lsp.Attributes; 5 | using Draco.Lsp.Model; 6 | 7 | namespace Draco.Lsp.Server.Language; 8 | 9 | [ClientCapability("TextDocument.CodeAction")] 10 | public interface ICodeAction 11 | { 12 | [ServerCapability(nameof(ServerCapabilities.CodeActionProvider))] 13 | public ICodeActionOptions Capability => this.CodeActionRegistrationOptions; 14 | 15 | [RegistrationOptions("textDocument/codeAction")] 16 | public CodeActionRegistrationOptions CodeActionRegistrationOptions { get; } 17 | 18 | [Request("textDocument/codeAction")] 19 | public Task>?> CodeActionAsync(CodeActionParams param, CancellationToken cancellationToken); 20 | } 21 | -------------------------------------------------------------------------------- /src/Draco.Lsp/Server/Language/ICodeCompletion.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | using Draco.Lsp.Attributes; 5 | using Draco.Lsp.Model; 6 | 7 | namespace Draco.Lsp.Server.Language; 8 | 9 | [ClientCapability("TextDocument.Completion")] 10 | public interface ICodeCompletion 11 | { 12 | [ServerCapability(nameof(ServerCapabilities.CompletionProvider))] 13 | public ICompletionOptions Capability => this.CompletionRegistrationOptions; 14 | 15 | [RegistrationOptions("textDocument/completion")] 16 | public CompletionRegistrationOptions CompletionRegistrationOptions { get; } 17 | 18 | [Request("textDocument/completion")] 19 | public Task> CompleteAsync(CompletionParams param, CancellationToken cancellationToken); 20 | } 21 | -------------------------------------------------------------------------------- /src/Draco.Lsp/Server/Language/IFindReferences.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | using Draco.Lsp.Attributes; 5 | using Draco.Lsp.Model; 6 | 7 | namespace Draco.Lsp.Server.Language; 8 | 9 | [ClientCapability("TextDocument.References")] 10 | public interface IFindReferences 11 | { 12 | [ServerCapability(nameof(ServerCapabilities.ReferencesProvider))] 13 | public IReferenceOptions Capability => this.FindReferencesRegistrationOptions; 14 | 15 | [RegistrationOptions("textDocument/references")] 16 | public ReferenceRegistrationOptions FindReferencesRegistrationOptions { get; } 17 | 18 | [Request("textDocument/references")] 19 | public Task> FindReferencesAsync(ReferenceParams param, CancellationToken cancellationToken); 20 | } 21 | -------------------------------------------------------------------------------- /src/Draco.Lsp/Server/Language/IGotoDefinition.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | using Draco.Lsp.Attributes; 5 | using Draco.Lsp.Model; 6 | 7 | namespace Draco.Lsp.Server.Language; 8 | 9 | [ClientCapability("TextDocument.Definition")] 10 | public interface IGotoDefinition 11 | { 12 | [ServerCapability(nameof(ServerCapabilities.DefinitionProvider))] 13 | public IDefinitionOptions Capability => this.GotoDefinitionRegistrationOptions; 14 | 15 | [RegistrationOptions("textDocument/definition")] 16 | public DefinitionRegistrationOptions GotoDefinitionRegistrationOptions { get; } 17 | 18 | [Request("textDocument/definition")] 19 | public Task> GotoDefinitionAsync(DefinitionParams param, CancellationToken cancellationToken); 20 | } 21 | -------------------------------------------------------------------------------- /src/Draco.Lsp/Server/Language/IHover.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | using Draco.Lsp.Attributes; 4 | using Draco.Lsp.Model; 5 | 6 | namespace Draco.Lsp.Server.Language; 7 | 8 | [ClientCapability("TextDocument.Hover")] 9 | public interface IHover 10 | { 11 | [ServerCapability(nameof(ServerCapabilities.HoverProvider))] 12 | public IHoverOptions Capability => this.HoverRegistrationOptions; 13 | 14 | [RegistrationOptions("textDocument/hover")] 15 | public HoverRegistrationOptions HoverRegistrationOptions { get; } 16 | 17 | [Request("textDocument/hover")] 18 | public Task HoverAsync(HoverParams param, CancellationToken cancellationToken); 19 | } 20 | -------------------------------------------------------------------------------- /src/Draco.Lsp/Server/Language/IInlayHint.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | using Draco.Lsp.Attributes; 5 | using Draco.Lsp.Model; 6 | 7 | namespace Draco.Lsp.Server.Language; 8 | 9 | [ClientCapability("TextDocument.InlayHint")] 10 | public interface IInlayHint 11 | { 12 | [ServerCapability(nameof(ServerCapabilities.InlayHintProvider))] 13 | public IInlayHintOptions Capability => this.InlayHintRegistrationOptions; 14 | 15 | [RegistrationOptions("textDocument/inlayHint")] 16 | public InlayHintRegistrationOptions InlayHintRegistrationOptions { get; } 17 | 18 | [Request("textDocument/inlayHint")] 19 | public Task> InlayHintAsync(InlayHintParams param, CancellationToken cancellationToken); 20 | } 21 | -------------------------------------------------------------------------------- /src/Draco.Lsp/Server/Language/IRename.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | using Draco.Lsp.Attributes; 4 | using Draco.Lsp.Model; 5 | 6 | namespace Draco.Lsp.Server.Language; 7 | 8 | [ClientCapability("TextDocument.Rename")] 9 | public interface IRename 10 | { 11 | [ServerCapability(nameof(ServerCapabilities.RenameProvider))] 12 | public IRenameOptions Capability => this.RenameRegistrationOptions; 13 | 14 | [RegistrationOptions("textDocument/rename")] 15 | public RenameRegistrationOptions RenameRegistrationOptions { get; } 16 | 17 | [Request("textDocument/rename")] 18 | public Task RenameAsync(RenameParams param, CancellationToken cancellationToken); 19 | } 20 | -------------------------------------------------------------------------------- /src/Draco.Lsp/Server/Language/ISignatureHelp.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | using Draco.Lsp.Attributes; 4 | using Draco.Lsp.Model; 5 | 6 | namespace Draco.Lsp.Server.Language; 7 | 8 | [ClientCapability("TextDocument.SignatureHelp")] 9 | public interface ISignatureHelp 10 | { 11 | [ServerCapability(nameof(ServerCapabilities.SignatureHelpProvider))] 12 | public ISignatureHelpOptions Capability => this.SignatureHelpRegistrationOptions; 13 | 14 | [RegistrationOptions("textDocument/signatureHelp")] 15 | public SignatureHelpRegistrationOptions SignatureHelpRegistrationOptions { get; } 16 | 17 | [Request("textDocument/signatureHelp")] 18 | public Task SignatureHelpAsync(SignatureHelpParams param, CancellationToken cancellationToken); 19 | } 20 | -------------------------------------------------------------------------------- /src/Draco.Lsp/Server/Language/ITextDocumentFormatting.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | using Draco.Lsp.Attributes; 5 | using Draco.Lsp.Model; 6 | 7 | namespace Draco.Lsp.Server.Language; 8 | 9 | [ClientCapability("TextDocument.Formatting")] 10 | public interface ITextDocumentFormatting 11 | { 12 | [ServerCapability(nameof(ServerCapabilities.DocumentFormattingProvider))] 13 | public IDocumentFormattingOptions Capability => this.DocumentFormattingRegistrationOptions; 14 | 15 | [RegistrationOptions("textDocument/formatting")] 16 | public DocumentFormattingRegistrationOptions DocumentFormattingRegistrationOptions { get; } 17 | 18 | [Request("textDocument/formatting")] 19 | public Task?> FormatTextDocumentAsync(DocumentFormattingParams param, CancellationToken cancellationToken); 20 | } 21 | -------------------------------------------------------------------------------- /src/Draco.Lsp/Server/LanguageClientProxy.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using Draco.JsonRpc; 3 | 4 | namespace Draco.Lsp.Server; 5 | 6 | // NOTE: Not sealed since DispatchProxy generates a class derived from this at runtime 7 | internal class LanguageClientProxy : JsonRpcClientProxy 8 | { 9 | protected override IJsonRpcMethodHandler CreateHandler(MethodInfo method) => 10 | LanguageServerMethodHandler.Create(method, this); 11 | } 12 | -------------------------------------------------------------------------------- /src/Draco.Lsp/Server/TextDocument/ITextDocumentDidChange.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Draco.Lsp.Attributes; 3 | using Draco.Lsp.Model; 4 | 5 | namespace Draco.Lsp.Server.TextDocument; 6 | 7 | [ClientCapability("TextDocument.Synchronization")] 8 | public interface ITextDocumentDidChange 9 | { 10 | [RegistrationOptions("textDocument/didChange")] 11 | public TextDocumentChangeRegistrationOptions DidChangeRegistrationOptions { get; } 12 | 13 | [Notification("textDocument/didChange", Mutating = true)] 14 | public Task TextDocumentDidChangeAsync(DidChangeTextDocumentParams param); 15 | } 16 | -------------------------------------------------------------------------------- /src/Draco.Lsp/Server/TextDocument/ITextDocumentDidClose.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Draco.Lsp.Attributes; 3 | using Draco.Lsp.Model; 4 | 5 | namespace Draco.Lsp.Server.TextDocument; 6 | 7 | [ClientCapability("TextDocument.Synchronization")] 8 | public interface ITextDocumentDidClose 9 | { 10 | [RegistrationOptions("textDocument/didClose")] 11 | public TextDocumentRegistrationOptions DidCloseRegistrationOptions { get; } 12 | 13 | [Notification("textDocument/didClose", Mutating = true)] 14 | public Task TextDocumentDidCloseAsync(DidCloseTextDocumentParams param); 15 | } 16 | -------------------------------------------------------------------------------- /src/Draco.Lsp/Server/TextDocument/ITextDocumentDidOpen.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Draco.Lsp.Attributes; 3 | using Draco.Lsp.Model; 4 | 5 | namespace Draco.Lsp.Server.TextDocument; 6 | 7 | [ClientCapability("TextDocument.Synchronization")] 8 | public interface ITextDocumentDidOpen 9 | { 10 | [RegistrationOptions("textDocument/didOpen")] 11 | public TextDocumentRegistrationOptions DidOpenRegistrationOptions { get; } 12 | 13 | [Notification("textDocument/didOpen", Mutating = true)] 14 | public Task TextDocumentDidOpenAsync(DidOpenTextDocumentParams param); 15 | } 16 | -------------------------------------------------------------------------------- /src/Draco.Lsp/Server/Workspace/IDidChangeConfiguration.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Draco.Lsp.Attributes; 3 | using Draco.Lsp.Model; 4 | 5 | namespace Draco.Lsp.Server.Workspace; 6 | 7 | [ClientCapability("Workspace.DidChangeConfiguration")] 8 | public interface IDidChangeConfiguration 9 | { 10 | [RegistrationOptions("workspace/didChangeConfiguration")] 11 | public object DidChangeConfigurationRegistrationOptions => new(); 12 | 13 | // NOTE: https://github.com/microsoft/vscode-languageserver-node/issues/380 14 | // The config might not be here, use the notification as an opportunity to re-pull settings 15 | [Notification("workspace/didChangeConfiguration", Mutating = true)] 16 | public Task DidChangeConfigurationAsync(DidChangeConfigurationParams param); 17 | } 18 | -------------------------------------------------------------------------------- /src/Draco.Lsp/Server/Workspace/IDidDeleteFiles.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Draco.Lsp.Attributes; 3 | using Draco.Lsp.Model; 4 | 5 | namespace Draco.Lsp.Server.Workspace; 6 | 7 | [ClientCapability("Workspace.FileOperations")] 8 | public interface IDidDeleteFiles 9 | { 10 | [RegistrationOptions("workspace/didDeleteFiles")] 11 | public FileOperationRegistrationOptions DidDeleteFileRegistrationOptions { get; } 12 | 13 | [Notification("workspace/didDeleteFiles", Mutating = true)] 14 | public Task DidDeleteFilesAsync(DeleteFilesParams param); 15 | } 16 | -------------------------------------------------------------------------------- /src/Draco.ProjectSystem/Draco.ProjectSystem.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/Draco.ProjectSystem/StringWriterLogger.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using Microsoft.Build.Framework; 3 | 4 | namespace Draco.ProjectSystem; 5 | 6 | internal sealed class StringWriterLogger(StringWriter writer) : ILogger 7 | { 8 | public LoggerVerbosity Verbosity { get; set; } = LoggerVerbosity.Detailed; 9 | public string? Parameters { get => null; set { } } 10 | 11 | public void Initialize(IEventSource eventSource) 12 | { 13 | eventSource.AnyEventRaised += (sender, e) => writer.WriteLine(e.Message); 14 | } 15 | 16 | public void Shutdown() { } 17 | } 18 | -------------------------------------------------------------------------------- /src/Draco.ProjectSystem/Unit.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.ProjectSystem; 2 | 3 | /// 4 | /// A unit type representing the absence of a value. 5 | /// 6 | public readonly record struct Unit 7 | { 8 | /// 9 | /// A default instance of the unit type. 10 | /// 11 | public static readonly Unit Default = default; 12 | } 13 | -------------------------------------------------------------------------------- /src/Draco.ProjectTemplates/README.md: -------------------------------------------------------------------------------- 1 | # Draco project templates 2 | 3 | This folder contains a collection of default Draco project templates usable with the `dotnet new` command. 4 | 5 | ## Console 6 | ```powershell 7 | dotnet new console --language draco 8 | ``` 9 | Creates a standard console application. 10 | 11 | ### Flags 12 | - `-f|--framework `: Sets the framework version in the `.dracoproj` file. 13 | -------------------------------------------------------------------------------- /src/Draco.ProjectTemplates/templates/console/DracoConsole.dracoproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Exe 4 | $(TargetFramework) 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/Draco.ProjectTemplates/templates/console/main.draco: -------------------------------------------------------------------------------- 1 | import System.Console; 2 | 3 | func main() { 4 | WriteLine("Hello world!"); 5 | } 6 | -------------------------------------------------------------------------------- /src/Draco.Repl/Draco.Repl.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | 6 | 7 | true 8 | dracorepl 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/Draco.Repl/InterfaceColor.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.Repl; 2 | 3 | /// 4 | /// The different color keys for the REPL interface. 5 | /// 6 | internal enum InterfaceColor 7 | { 8 | /// 9 | /// The prompt text color. 10 | /// 11 | PromptColor, 12 | 13 | /// 14 | /// The error message color. 15 | /// 16 | ErrorColor, 17 | } 18 | -------------------------------------------------------------------------------- /src/Draco.Repl/Program.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using PrettyPrompt.Consoles; 3 | 4 | namespace Draco.Repl; 5 | 6 | internal static class Program 7 | { 8 | internal static async Task Main(string[] args) 9 | { 10 | var configuration = new Configuration(); 11 | var console = new SystemConsole(); 12 | 13 | var loop = new Loop(configuration, console); 14 | await loop.Run(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Draco.Sdk/Draco.Sdk.msbuildproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | MSBuildSdk 5 | netstandard2.0 6 | true 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | <_File Include="Sdk\**\*.*" /> 16 | 17 | 18 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/Draco.Sdk/Sdk/Sdk.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #{DRACO_VERSION} 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/Draco.Sdk/Sdk/Sdk.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildToolsPath)\Microsoft.Common.CrossTargeting.targets 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/Draco.SourceGeneration/BoundTree/BoundTreeSourceGenerator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading; 4 | using Microsoft.CodeAnalysis; 5 | 6 | namespace Draco.SourceGeneration.BoundTree; 7 | 8 | [Generator] 9 | public sealed class BoundTreeSourceGenerator : XmlSourceGenerator 10 | { 11 | protected override string XmlFileName => "BoundNodes.xml"; 12 | 13 | protected override Type XmlModelType => typeof(XmlTree); 14 | 15 | protected override IEnumerable> GenerateSources(object xmlModel, CancellationToken cancellationToken) 16 | { 17 | var domainModel = Tree.FromXml((XmlTree)xmlModel); 18 | 19 | var boundTreeCode = Template.Generate(domainModel); 20 | 21 | return 22 | [ 23 | new("BoundTree.Generated.cs", boundTreeCode), 24 | ]; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Draco.SourceGeneration/Dap/CsModel/Class.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Draco.SourceGeneration.Dap.CsModel; 4 | 5 | /// 6 | /// A class declaration. 7 | /// 8 | public sealed class Class : Declaration 9 | { 10 | /// 11 | /// The base of this class. 12 | /// 13 | public Class? Base { get; set; } 14 | 15 | /// 16 | /// The nested declarations within this class. 17 | /// 18 | public IList NestedDeclarations { get; set; } = []; 19 | 20 | /// 21 | /// The properties within this class. 22 | /// 23 | public IList Properties { get; set; } = []; 24 | } 25 | -------------------------------------------------------------------------------- /src/Draco.SourceGeneration/Dap/CsModel/Declaration.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.SourceGeneration.Dap.CsModel; 2 | 3 | /// 4 | /// The base of all declarations. 5 | /// 6 | public abstract class Declaration 7 | { 8 | /// 9 | /// The docs of this declaration. 10 | /// 11 | public string? Documentation { get; set; } 12 | 13 | /// 14 | /// The name of this declaration. 15 | /// 16 | public string Name { get; set; } = string.Empty; 17 | } 18 | -------------------------------------------------------------------------------- /src/Draco.SourceGeneration/Dap/CsModel/Enum.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace Draco.SourceGeneration.Dap.CsModel; 5 | 6 | /// 7 | /// An enum declaration. 8 | /// 9 | public sealed class Enum : Declaration 10 | { 11 | /// 12 | /// True, if this is a string enum. 13 | /// 14 | public bool IsStringEnum => this.Members.Any(m => m.Value is string); 15 | 16 | /// 17 | /// The members within this enum. 18 | /// 19 | public IList Members { get; set; } = []; 20 | } 21 | -------------------------------------------------------------------------------- /src/Draco.SourceGeneration/Dap/CsModel/EnumMember.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.SourceGeneration.Dap.CsModel; 2 | 3 | /// 4 | /// A single enum member. 5 | /// 6 | public sealed class EnumMember : Declaration 7 | { 8 | /// 9 | /// The value of this enum member. 10 | /// 11 | public object? Value { get; set; } 12 | } 13 | -------------------------------------------------------------------------------- /src/Draco.SourceGeneration/Dap/CsModel/Model.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Draco.SourceGeneration.Dap.CsModel; 4 | 5 | /// 6 | /// The C# model of the DAP code. 7 | /// 8 | public sealed class Model 9 | { 10 | /// 11 | /// The declarations of the model. 12 | /// 13 | public IList Declarations { get; set; } = []; 14 | } 15 | -------------------------------------------------------------------------------- /src/Draco.SourceGeneration/Dap/CsModel/Property.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.SourceGeneration.Dap.CsModel; 2 | 3 | /// 4 | /// A property definition. 5 | /// 6 | public sealed class Property : Declaration 7 | { 8 | /// 9 | /// The property type. 10 | /// 11 | public Type Type { get; set; } = null!; 12 | 13 | /// 14 | /// The property name when serialized. 15 | /// 16 | public string SerializedName { get; set; } = string.Empty; 17 | 18 | /// 19 | /// True if the property should be omitted, if it's null. 20 | /// 21 | public bool OmitIfNull { get; set; } 22 | 23 | /// 24 | /// The value of the enumeration member. 25 | /// 26 | public object? Value { get; set; } 27 | 28 | /// 29 | /// True, if the property is required. 30 | /// 31 | public bool IsRequired => !this.OmitIfNull && this.Value is null; 32 | } 33 | -------------------------------------------------------------------------------- /src/Draco.SourceGeneration/Dap/DapModel.xsd: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/Draco.SourceGeneration/Dap/DomainConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace Draco.SourceGeneration.Dap; 5 | 6 | public sealed class Config(IList builtinTypes) 7 | { 8 | public static Config FromXml(XmlConfig config) 9 | { 10 | var basicAssembly = typeof(object).Assembly; 11 | var builtins = config.BuiltinTypes 12 | .Select(b => new BuiltinType(b.Name, b.FullName)) 13 | .ToList(); 14 | return new(builtins); 15 | } 16 | 17 | public IList BuiltinTypes { get; } = builtinTypes; 18 | } 19 | 20 | public readonly record struct BuiltinType(string Name, string FullName); 21 | -------------------------------------------------------------------------------- /src/Draco.SourceGeneration/Dap/XmlConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Xml.Serialization; 3 | 4 | namespace Draco.SourceGeneration.Dap; 5 | 6 | [XmlRoot(ElementName = "DapModel", Namespace = "http://draco-lang.com/debug-adapter-protocol/model")] 7 | public sealed class XmlConfig 8 | { 9 | [XmlElement("BuiltinType")] 10 | public List BuiltinTypes { get; set; } = null!; 11 | } 12 | 13 | [XmlRoot(ElementName = "BuiltinType")] 14 | public sealed class XmlBuiltinType 15 | { 16 | [XmlAttribute] 17 | public string Name { get; set; } = string.Empty; 18 | 19 | [XmlAttribute] 20 | public string FullName { get; set; } = string.Empty; 21 | } 22 | -------------------------------------------------------------------------------- /src/Draco.SourceGeneration/EmbeddedResourceLoader.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Reflection; 3 | 4 | namespace Draco.SourceGeneration; 5 | 6 | public static class EmbeddedResourceLoader 7 | { 8 | public static StreamReader GetManifestResourceStreamReader(string prefix, string name) 9 | { 10 | var fullName = $"{prefix}.{name}"; 11 | var assembly = Assembly.GetExecutingAssembly(); 12 | var stream = assembly.GetManifestResourceStream(fullName) 13 | ?? throw new FileNotFoundException($"resource {fullName} was not embedded in the assembly"); 14 | var reader = new StreamReader(stream); 15 | return reader; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Draco.SourceGeneration/EnumerableExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Draco.SourceGeneration; 4 | 5 | /// 6 | /// Polyfill for ns2.0 things. 7 | /// 8 | internal static class EnumerableExtensions 9 | { 10 | public static HashSet ToHashSet(this IEnumerable items, EqualityComparer? comparer = null) 11 | { 12 | comparer ??= EqualityComparer.Default; 13 | var result = new HashSet(comparer); 14 | foreach (var item in items) result.Add(item); 15 | return result; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Draco.SourceGeneration/Lsp/CsModel/Class.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Draco.SourceGeneration.Lsp.CsModel; 4 | 5 | /// 6 | /// A class declaration. 7 | /// 8 | public sealed class Class : Declaration 9 | { 10 | /// 11 | /// The parent of this class in terms of containment, not inheritance. 12 | /// 13 | public Class? Parent { get; set; } 14 | 15 | /// 16 | /// The interfaces this class implements. 17 | /// 18 | public IList Interfaces { get; set; } = []; 19 | 20 | /// 21 | /// The declarations this class has nested within it. 22 | /// 23 | public IList NestedDeclarations { get; set; } = []; 24 | 25 | /// 26 | /// The properties within this class. 27 | /// 28 | public IList Properties { get; set; } = []; 29 | } 30 | -------------------------------------------------------------------------------- /src/Draco.SourceGeneration/Lsp/CsModel/Declaration.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.SourceGeneration.Lsp.CsModel; 2 | 3 | /// 4 | /// The base of all declarations. 5 | /// 6 | public abstract class Declaration 7 | { 8 | /// 9 | /// The docs of this declaration. 10 | /// 11 | public string? Documentation { get; set; } 12 | 13 | /// 14 | /// The deprecation message, if any. 15 | /// 16 | public string? Deprecated { get; set; } 17 | 18 | /// 19 | /// The version since this declaration was introduced. 20 | /// 21 | public string? SinceVersion { get; set; } 22 | 23 | /// 24 | /// True, if this declaration is only proposed, not necessarily final. 25 | /// 26 | public bool IsProposed { get; set; } 27 | 28 | /// 29 | /// The name of this declaration. 30 | /// 31 | public string Name { get; set; } = string.Empty; 32 | } 33 | -------------------------------------------------------------------------------- /src/Draco.SourceGeneration/Lsp/CsModel/Enum.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace Draco.SourceGeneration.Lsp.CsModel; 5 | 6 | /// 7 | /// An enum declaration. 8 | /// 9 | public sealed class Enum : Declaration 10 | { 11 | /// 12 | /// True, if this is a string enum. 13 | /// 14 | public bool IsStringEnum => this.Members.Any(m => m.Value is string); 15 | 16 | /// 17 | /// The members within this enum. 18 | /// 19 | public IList Members { get; set; } = []; 20 | } 21 | -------------------------------------------------------------------------------- /src/Draco.SourceGeneration/Lsp/CsModel/EnumMember.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.SourceGeneration.Lsp.CsModel; 2 | 3 | /// 4 | /// A single enum member. 5 | /// 6 | public sealed class EnumMember : Declaration 7 | { 8 | /// 9 | /// The value of this enum member. 10 | /// 11 | public object? Value { get; set; } 12 | } 13 | -------------------------------------------------------------------------------- /src/Draco.SourceGeneration/Lsp/CsModel/Interface.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Draco.SourceGeneration.Lsp.CsModel; 4 | 5 | /// 6 | /// An interface declaration. 7 | /// 8 | public sealed class Interface : Declaration 9 | { 10 | /// 11 | /// The interfaces this interface implements. 12 | /// 13 | public IList Interfaces { get; set; } = []; 14 | 15 | /// 16 | /// The properties within this interface. 17 | /// 18 | public IList Properties { get; set; } = []; 19 | } 20 | -------------------------------------------------------------------------------- /src/Draco.SourceGeneration/Lsp/CsModel/Model.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Draco.SourceGeneration.Lsp.CsModel; 4 | 5 | /// 6 | /// The C# model of the LSP code. 7 | /// 8 | public sealed class Model 9 | { 10 | /// 11 | /// The declarations of the model. 12 | /// 13 | public IList Declarations { get; set; } = []; 14 | } 15 | -------------------------------------------------------------------------------- /src/Draco.SourceGeneration/Lsp/DomainConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace Draco.SourceGeneration.Lsp; 5 | 6 | public sealed class Config(IList builtinTypes) 7 | { 8 | public static Config FromXml(XmlConfig config) 9 | { 10 | var basicAssembly = typeof(object).Assembly; 11 | var builtins = config.BuiltinTypes 12 | .Select(b => new BuiltinType(b.Name, b.FullName)) 13 | .ToList(); 14 | return new(builtins); 15 | } 16 | 17 | public IList BuiltinTypes { get; } = builtinTypes; 18 | } 19 | 20 | public readonly record struct BuiltinType(string Name, string FullName); 21 | -------------------------------------------------------------------------------- /src/Draco.SourceGeneration/Lsp/LspModel.xsd: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/Draco.SourceGeneration/Lsp/Metamodel/AggregateType.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.SourceGeneration.Lsp.Metamodel; 2 | 3 | /// 4 | /// Includes AndType, OrType, TupleType. 5 | /// 6 | internal sealed record class AggregateType : Type 7 | { 8 | public override required string Kind { get; set; } 9 | 10 | public required EquatableArray Items { get; set; } 11 | } 12 | -------------------------------------------------------------------------------- /src/Draco.SourceGeneration/Lsp/Metamodel/ArrayType.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.SourceGeneration.Lsp.Metamodel; 2 | 3 | /// 4 | /// Represents an array type (e.g. `TextDocument[]`). 5 | /// 6 | internal sealed record class ArrayType : Type 7 | { 8 | public override required string Kind { get; set; } 9 | 10 | public required Type Element { get; set; } 11 | } 12 | -------------------------------------------------------------------------------- /src/Draco.SourceGeneration/Lsp/Metamodel/Enumeration.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Draco.SourceGeneration.Lsp.Metamodel; 4 | 5 | /// 6 | /// Defines an enumeration. 7 | /// 8 | internal sealed class Enumeration : IDeclaration 9 | { 10 | public required string Name { get; set; } 11 | public string? Documentation { get; set; } 12 | public string? Since { get; set; } 13 | public bool? Proposed { get; set; } 14 | public string? Deprecated { get; set; } 15 | 16 | /// 17 | /// The type of the elements. 18 | /// 19 | public required NamedType Type { get; set; } 20 | 21 | /// 22 | /// The enum values. 23 | /// 24 | public required IList Values { get; set; } 25 | 26 | /// 27 | /// Whether the enumeration supports custom values (e.g. values which are not 28 | /// part of the set defined in `values`). If omitted no custom values are 29 | /// supported. 30 | /// 31 | public bool? SupportsCustomValues { get; set; } 32 | } 33 | -------------------------------------------------------------------------------- /src/Draco.SourceGeneration/Lsp/Metamodel/EnumerationEntry.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.SourceGeneration.Lsp.Metamodel; 2 | 3 | /// 4 | /// Defines an enumeration entry. 5 | /// 6 | internal sealed class EnumerationEntry : IDeclaration 7 | { 8 | public required string Name { get; set; } 9 | public string? Documentation { get; set; } 10 | public string? Since { get; set; } 11 | public bool? Proposed { get; set; } 12 | public string? Deprecated { get; set; } 13 | 14 | /// 15 | /// The value. 16 | /// 17 | public required object Value { get; set; } 18 | } 19 | -------------------------------------------------------------------------------- /src/Draco.SourceGeneration/Lsp/Metamodel/IDeclaration.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.SourceGeneration.Lsp.Metamodel; 2 | 3 | /// 4 | /// Represents a TS documented declaration in the metamodel. 5 | /// 6 | internal interface IDeclaration : IDocumented 7 | { 8 | /// 9 | /// The name of the declaration element. 10 | /// 11 | public string Name { get; set; } 12 | } 13 | -------------------------------------------------------------------------------- /src/Draco.SourceGeneration/Lsp/Metamodel/IDocumented.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.SourceGeneration.Lsp.Metamodel; 2 | 3 | /// 4 | /// Represents a TS metamodel element that's documented, but not necessarily named. 5 | /// 6 | internal interface IDocumented 7 | { 8 | /// 9 | /// An optional documentation. 10 | /// 11 | public string? Documentation { get; set; } 12 | 13 | /// 14 | /// Since when (release number) this element is 15 | /// available.Is undefined if not known. 16 | /// 17 | public string? Since { get; set; } 18 | 19 | /// 20 | /// Whether this is a proposed element. If omitted, 21 | /// the declaration is final. 22 | /// 23 | public bool? Proposed { get; set; } 24 | 25 | /// 26 | /// Whether the element is deprecated or not. If deprecated 27 | /// the property contains the deprecation message. 28 | /// 29 | public string? Deprecated { get; set; } 30 | } 31 | -------------------------------------------------------------------------------- /src/Draco.SourceGeneration/Lsp/Metamodel/LiteralType.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.SourceGeneration.Lsp.Metamodel; 2 | 3 | /// 4 | /// Includes StringLiteralType, IntegerLiteralType, BooleanLiteralType. 5 | /// 6 | internal sealed record class LiteralType : Type 7 | { 8 | public override required string Kind { get; set; } 9 | 10 | public required object Value { get; set; } 11 | } 12 | -------------------------------------------------------------------------------- /src/Draco.SourceGeneration/Lsp/Metamodel/MapType.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.SourceGeneration.Lsp.Metamodel; 2 | 3 | /// 4 | /// Represents a JSON object map 5 | /// (e.g. `interface Map<K extends string | integer, V> { [key: K] => V; }`). 6 | /// 7 | internal sealed record class MapType : Type 8 | { 9 | public override required string Kind { get; set; } 10 | 11 | public required NamedType Key { get; set; } 12 | 13 | public required Type Value { get; set; } 14 | } 15 | -------------------------------------------------------------------------------- /src/Draco.SourceGeneration/Lsp/Metamodel/MessageDirection.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.SourceGeneration.Lsp.Metamodel; 2 | 3 | /// 4 | /// Indicates in which direction a message is sent in the protocol. 5 | /// 6 | internal enum MessageDirection 7 | { 8 | ClientToServer, 9 | ServerToClient, 10 | Both, 11 | } 12 | -------------------------------------------------------------------------------- /src/Draco.SourceGeneration/Lsp/Metamodel/MetaData.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.SourceGeneration.Lsp.Metamodel; 2 | 3 | internal sealed class MetaData 4 | { 5 | /// 6 | /// The protocol version. 7 | /// 8 | public required string Version { get; set; } 9 | } 10 | -------------------------------------------------------------------------------- /src/Draco.SourceGeneration/Lsp/Metamodel/MetaModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Draco.SourceGeneration.Lsp.Metamodel; 4 | 5 | /// 6 | /// The actual meta model. 7 | /// 8 | internal sealed class MetaModel 9 | { 10 | /// 11 | /// Additional meta data. 12 | /// 13 | public MetaData MetaData { get; set; } = null!; 14 | 15 | /// 16 | /// The requests. 17 | /// 18 | public required IList Requests { get; set; } 19 | 20 | /// 21 | /// The notifications. 22 | /// 23 | public required IList Notifications { get; set; } 24 | 25 | /// 26 | /// The structures. 27 | /// 28 | public required IList Structures { get; set; } 29 | 30 | /// 31 | /// The enumerations. 32 | /// 33 | public required IList Enumerations { get; set; } 34 | 35 | /// 36 | /// The type aliases. 37 | /// 38 | public required IList TypeAliases { get; set; } 39 | } 40 | -------------------------------------------------------------------------------- /src/Draco.SourceGeneration/Lsp/Metamodel/NamedType.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.SourceGeneration.Lsp.Metamodel; 2 | 3 | /// 4 | /// Includes BaseType, ReferenceType, EnumerationType, MapKeyType. 5 | /// 6 | internal sealed record class NamedType : Type 7 | { 8 | public override required string Kind { get; set; } 9 | 10 | /// 11 | /// The name of the type. 12 | /// 13 | public required string Name { get; set; } 14 | } 15 | -------------------------------------------------------------------------------- /src/Draco.SourceGeneration/Lsp/Metamodel/StructureLiteral.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.SourceGeneration.Lsp.Metamodel; 2 | 3 | /// 4 | /// Defines an unnamed structure of an object literal. 5 | /// 6 | internal sealed record class StructureLiteral : IDocumented 7 | { 8 | public string? Documentation { get; set; } 9 | public string? Since { get; set; } 10 | public bool? Proposed { get; set; } 11 | public string? Deprecated { get; set; } 12 | 13 | /// 14 | /// The properties. 15 | /// 16 | public required EquatableArray Properties { get; set; } 17 | } 18 | -------------------------------------------------------------------------------- /src/Draco.SourceGeneration/Lsp/Metamodel/StructureLiteralType.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.SourceGeneration.Lsp.Metamodel; 2 | 3 | /// 4 | /// Represents a literal structure 5 | /// (e.g. `property: { start: uinteger; end: uinteger; }`). 6 | /// 7 | internal sealed record class StructureLiteralType : Type 8 | { 9 | public override required string Kind { get; set; } 10 | 11 | public StructureLiteral Value { get; set; } = null!; 12 | } 13 | -------------------------------------------------------------------------------- /src/Draco.SourceGeneration/Lsp/Metamodel/Type.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.SourceGeneration.Lsp.Metamodel; 2 | 3 | internal abstract record class Type 4 | { 5 | /// 6 | /// The discriminating type kind. 7 | /// 8 | public abstract string Kind { get; set; } 9 | } 10 | -------------------------------------------------------------------------------- /src/Draco.SourceGeneration/Lsp/Metamodel/TypeAlias.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.SourceGeneration.Lsp.Metamodel; 2 | 3 | /// 4 | /// Defines a type alias. 5 | /// (e.g. `type Definition = Location | LocationLink`) 6 | /// 7 | internal sealed class TypeAlias : IDeclaration 8 | { 9 | public required string Name { get; set; } 10 | public string? Documentation { get; set; } 11 | public string? Since { get; set; } 12 | public bool? Proposed { get; set; } 13 | public string? Deprecated { get; set; } 14 | 15 | /// 16 | /// The aliased type. 17 | /// 18 | public required Type Type { get; set; } 19 | } 20 | -------------------------------------------------------------------------------- /src/Draco.SourceGeneration/Lsp/XmlConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Xml.Serialization; 3 | 4 | namespace Draco.SourceGeneration.Lsp; 5 | 6 | [XmlRoot(ElementName = "LspModel", Namespace = "http://draco-lang.com/language-server-protocol/model")] 7 | public sealed class XmlConfig 8 | { 9 | [XmlElement("BuiltinType")] 10 | public List BuiltinTypes { get; set; } = null!; 11 | } 12 | 13 | [XmlRoot(ElementName = "BuiltinType")] 14 | public sealed class XmlBuiltinType 15 | { 16 | [XmlAttribute] 17 | public string Name { get; set; } = string.Empty; 18 | 19 | [XmlAttribute] 20 | public string FullName { get; set; } = string.Empty; 21 | } 22 | -------------------------------------------------------------------------------- /src/Draco.SourceGeneration/MappingEqualityComparer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Draco.SourceGeneration; 5 | 6 | internal static class MappingEqualityComparer 7 | { 8 | internal static IEqualityComparer Create(Func map) 9 | where TKey : IEquatable => new MappingEqualityComparerImpl(map); 10 | 11 | private sealed class MappingEqualityComparerImpl : EqualityComparer 12 | where TKey : IEquatable 13 | { 14 | private readonly Func map; 15 | 16 | internal MappingEqualityComparerImpl(Func map) 17 | { 18 | this.map = map; 19 | } 20 | 21 | public override bool Equals(TSource x, TSource y) => this.map(x).Equals(this.map(y)); 22 | public override int GetHashCode(TSource obj) => this.map(obj).GetHashCode(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Draco.SourceGeneration/OneOf/DomainConfig.cs: -------------------------------------------------------------------------------- 1 | namespace Draco.SourceGeneration.OneOf; 2 | 3 | public sealed class Config(string rootNamespace, int maxCases) 4 | { 5 | public static Config FromXml(XmlConfig config) => 6 | new(config.RootNamespace, config.MaxCases); 7 | 8 | public string RootNamespace { get; } = rootNamespace; 9 | public int MaxCases { get; } = maxCases; 10 | } 11 | -------------------------------------------------------------------------------- /src/Draco.SourceGeneration/OneOf/OneOf.xsd: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/Draco.SourceGeneration/OneOf/OneOfSourceGenerator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading; 4 | using Microsoft.CodeAnalysis; 5 | 6 | namespace Draco.SourceGeneration.OneOf; 7 | 8 | [Generator] 9 | public sealed class OneOfSourceGenerator : XmlSourceGenerator 10 | { 11 | protected override string XmlFileName => "OneOf.xml"; 12 | protected override Type XmlModelType => typeof(XmlConfig); 13 | 14 | protected override IEnumerable> GenerateSources(object xmlModel, CancellationToken cancellationToken) 15 | { 16 | var domainModel = Config.FromXml((XmlConfig)xmlModel); 17 | 18 | var oneOfCode = Template.Generate(domainModel); 19 | 20 | return 21 | [ 22 | new("OneOf.Generated.cs", oneOfCode), 23 | ]; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Draco.SourceGeneration/OneOf/XmlConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Xml.Serialization; 2 | 3 | namespace Draco.SourceGeneration.OneOf; 4 | 5 | [XmlRoot(ElementName = "OneOf", Namespace = "http://draco-lang.com/one-of")] 6 | public sealed class XmlConfig 7 | { 8 | [XmlAttribute] 9 | public string RootNamespace { get; set; } = string.Empty; 10 | 11 | [XmlAttribute] 12 | public int MaxCases { get; set; } 13 | } 14 | -------------------------------------------------------------------------------- /src/Draco.SourceGeneration/ReferenceEqualityComparer.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Runtime.CompilerServices; 3 | 4 | namespace Draco.SourceGeneration; 5 | 6 | /// 7 | /// Reimplementation of the BCL type because of ns2.0 target. 8 | /// 9 | internal sealed class ReferenceEqualityComparer : IEqualityComparer 10 | { 11 | public static ReferenceEqualityComparer Instance { get; } = new(); 12 | 13 | private ReferenceEqualityComparer() 14 | { 15 | } 16 | 17 | public new bool Equals(object? x, object? y) => ReferenceEquals(x, y); 18 | public int GetHashCode(object? obj) => RuntimeHelpers.GetHashCode(obj); 19 | } 20 | -------------------------------------------------------------------------------- /src/Draco.SourceGeneration/WellKnownTypes/WellKnownTypesSourceGenerator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading; 4 | using Microsoft.CodeAnalysis; 5 | 6 | namespace Draco.SourceGeneration.WellKnownTypes; 7 | 8 | [Generator] 9 | public sealed class WellKnownTypesSourceGenerator : XmlSourceGenerator 10 | { 11 | protected override string XmlFileName => "WellKnownTypes.xml"; 12 | protected override Type XmlModelType => typeof(XmlModel); 13 | 14 | protected override IEnumerable> GenerateSources(object xmlModel, CancellationToken cancellationToken) 15 | { 16 | var domainModel = WellKnownTypes.FromXml((XmlModel)xmlModel); 17 | 18 | var wellKnownTypesCode = Template.Generate(domainModel); 19 | 20 | return 21 | [ 22 | new("WellKnownTypes.Generated.cs", wellKnownTypesCode), 23 | ]; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Draco.SourceGeneration/WellKnownTypes/XmlModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Xml.Serialization; 3 | 4 | namespace Draco.SourceGeneration.WellKnownTypes; 5 | 6 | [XmlRoot(ElementName = "WellKnownTypes", Namespace = "http://draco-lang.com/symbols/well-known-types")] 7 | public sealed class XmlModel 8 | { 9 | [XmlElement("Assembly")] 10 | public List Assemblies { get; set; } = null!; 11 | 12 | [XmlElement("Type")] 13 | public List Types { get; set; } = null!; 14 | } 15 | 16 | [XmlRoot(ElementName = "Assembly")] 17 | public sealed class XmlAssembly 18 | { 19 | [XmlAttribute] 20 | public string Name { get; set; } = string.Empty; 21 | 22 | [XmlAttribute] 23 | public string PublicKeyToken { get; set; } = string.Empty; 24 | } 25 | 26 | [XmlRoot(ElementName = "Type")] 27 | public sealed class XmlType 28 | { 29 | [XmlAttribute] 30 | public string Name { get; set; } = string.Empty; 31 | 32 | [XmlAttribute] 33 | public string Assembly { get; set; } = string.Empty; 34 | } 35 | --------------------------------------------------------------------------------