From 838109d0b4612bce5bdd55a6d2cbc99074eeca34 Mon Sep 17 00:00:00 2001 From: "Mathias R. Jessen" Date: Wed, 21 Nov 2018 15:57:14 +0100 Subject: [PATCH 1/3] Add RFC: Native support for interface declarations --- ...tive-Support-for-Interface-Declarations.md | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 1-Draft/RFCNNNN-Native-Support-for-Interface-Declarations.md diff --git a/1-Draft/RFCNNNN-Native-Support-for-Interface-Declarations.md b/1-Draft/RFCNNNN-Native-Support-for-Interface-Declarations.md new file mode 100644 index 00000000..d7017dae --- /dev/null +++ b/1-Draft/RFCNNNN-Native-Support-for-Interface-Declarations.md @@ -0,0 +1,77 @@ +--- +RFC: RFCNNNN +Author: Mathias R. Jessen +Status: Draft +SupercededBy: N/A +Version: 0.1 +Area: Language +Comments Due: 2019-01-04 +Plan to implement: Yes +--- + +# Native Support for Interface Declarations + +The PowerShell Classes feature introduced in PowerShell 5.0 allows for type definitions at runtime. Since open sourcing PowerShell Core, one of the most oft-repeated feature request I've heard from community members is the ability to also declare and define interfaces at runtime, usually for ease of implementing common software design pattern such as the Builder pattern. + +## Motivation + + As a module author, + I can leverage common OO design patterns that require abstract type definitions, + so that my implementations are easily communicated and explained to other developers and module authors. + +## Specification + +Implementing native support for interface declarations require both syntactical and semantic changes to the language engine. + +### Syntax + +Based on the [original issue](https://github.com/PowerShell/PowerShell/issues/2223) raised by @vors, I imagine a simplified subset of the class syntax, as follows: + +```powershell +# interface declaration with no members +interface IMyInterface { } + +# interface declaration chaining declared members from another interface +interface IMyDisposable : IDisposable { } + +# interface declaration with a method +interface IMyInterfaceWithMethod { + [void] DoSomething([int]$IntParam) +} + +# interface declaration with a property +interface IMyInterfaceWithProperty { + [int]$MyProperty +} + +# interface declaration extending an existing interface with properties and methods +interface IMyExtendedInterfaceWithMembers { + [int]$MyProperty + + [void] DoSomething([int]$IntParam) +} +``` + +### Semantics + +Currently, when the parser recognizes a `class` or `enum` declaration, it produces a `TypeDefinitionAst` made up of `PropertyMemberAst` and `FunctionMemberAst` children. The type definition AST is then dispatched to either TypeDefiner.DefineTypeHelper or TypeDefiner.DefineEnumHelper for creating and emitting the corresponding runtime type. + +We can either add new `AbstractMemberAst` types specifically for the purpose of abstract type definitions, or modify the existing `MemberAst` types to account for abstract member constraints. + +Going with separate AST types for abstract type members would reduce the number of branches and special cases required in the rest of the code base, but the obvious benefit of reusing existing AST types for member declarations is that we can do not have to extend the existing AST visitor surface (ie. no `IAstVisitor3 : IAstVisitor2`, `AstVisitor3 : AstVisitor2, IAstVisitor3` etc.). This may present hidden parsing issues for tooling developers though. + +Regardless of design changes to the AST surface, we can either define a new `TypeDefiner.DefineInterfaceHelper` for emitting interface types, or we can modify the existing `DefineTypeHelper` definition to take the `Interface` attribute into account and modify all the other emitting functions being called by it. + +In my [prototype implementation](https://github.com/IISResetMe/PowerShell/tree/feature/interfaces), I've opted to: + + 1. extend the AST visitor surface with a set of `AbstractMemberAst` types, + 2. update the relevant AstVisitor interfaces and implementations, and + 3. dispatch type definition to a new `DefineInterfaceHelper` class + +## Alternate Proposals and Considerations + +There are a couple of open questions around the design and implementation of interface declaration support: + + - Should we allow control over getter/setter declarations? + - If so, should we replicate the syntax from C#? + - Existing class definitions need to [mark interface member implementations virtual](https://github.com/PowerShell/PowerShell/issues/8302) \ No newline at end of file From e2cd2f4c4abf7422ae826885bbdb5575dec31e7e Mon Sep 17 00:00:00 2001 From: "Mathias R. Jessen" Date: Wed, 21 Nov 2018 17:03:02 +0100 Subject: [PATCH 2/3] Update RFCNNNN-Native-Support-for-Interface-Declarations.md --- 1-Draft/RFCNNNN-Native-Support-for-Interface-Declarations.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/1-Draft/RFCNNNN-Native-Support-for-Interface-Declarations.md b/1-Draft/RFCNNNN-Native-Support-for-Interface-Declarations.md index d7017dae..0df3006c 100644 --- a/1-Draft/RFCNNNN-Native-Support-for-Interface-Declarations.md +++ b/1-Draft/RFCNNNN-Native-Support-for-Interface-Declarations.md @@ -9,7 +9,7 @@ Comments Due: 2019-01-04 Plan to implement: Yes --- -# Native Support for Interface Declarations +# Native Support for .NET Interface Declarations The PowerShell Classes feature introduced in PowerShell 5.0 allows for type definitions at runtime. Since open sourcing PowerShell Core, one of the most oft-repeated feature request I've heard from community members is the ability to also declare and define interfaces at runtime, usually for ease of implementing common software design pattern such as the Builder pattern. @@ -74,4 +74,4 @@ There are a couple of open questions around the design and implementation of int - Should we allow control over getter/setter declarations? - If so, should we replicate the syntax from C#? - - Existing class definitions need to [mark interface member implementations virtual](https://github.com/PowerShell/PowerShell/issues/8302) \ No newline at end of file + - Existing class definitions need to [mark interface member implementations virtual](https://github.com/PowerShell/PowerShell/issues/8302) From 075867348c5db4c5414fb1f286cf6f289bb3591c Mon Sep 17 00:00:00 2001 From: "Mathias R. Jessen" Date: Wed, 21 Nov 2018 19:14:02 +0100 Subject: [PATCH 3/3] Update RFCNNNN-Native-Support-for-Interface-Declarations.md --- ...tive-Support-for-Interface-Declarations.md | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/1-Draft/RFCNNNN-Native-Support-for-Interface-Declarations.md b/1-Draft/RFCNNNN-Native-Support-for-Interface-Declarations.md index 0df3006c..6f8cdd26 100644 --- a/1-Draft/RFCNNNN-Native-Support-for-Interface-Declarations.md +++ b/1-Draft/RFCNNNN-Native-Support-for-Interface-Declarations.md @@ -54,6 +54,30 @@ interface IMyExtendedInterfaceWithMembers { ### Semantics +The examples above would create new interface types exactly as if one had defined those using C# + +The following piece of code in PowerShell: + +```powershell +interface IMyInterface { + [int]$MyProperty + [void]MyMethod([string]$StringParam) +} +``` + +would produce IL completely identical to what the C# compiler would produce for the equivalent: + +```csharp +public interface IMyInterface { + int MyProperty { get; set; } + void MyMethod(string StringParam); +} +``` + +*Note: [C# 8 is slated to support default implementations](https://blogs.msdn.microsoft.com/dotnet/2018/11/12/building-c-8-0/) for interface methods, something we might want to consider as well* + +### Notes on potential changes to the AST surface + Currently, when the parser recognizes a `class` or `enum` declaration, it produces a `TypeDefinitionAst` made up of `PropertyMemberAst` and `FunctionMemberAst` children. The type definition AST is then dispatched to either TypeDefiner.DefineTypeHelper or TypeDefiner.DefineEnumHelper for creating and emitting the corresponding runtime type. We can either add new `AbstractMemberAst` types specifically for the purpose of abstract type definitions, or modify the existing `MemberAst` types to account for abstract member constraints. @@ -75,3 +99,4 @@ There are a couple of open questions around the design and implementation of int - Should we allow control over getter/setter declarations? - If so, should we replicate the syntax from C#? - Existing class definitions need to [mark interface member implementations virtual](https://github.com/PowerShell/PowerShell/issues/8302) + - Depending on community feedback and envisioned use cases, are interfaces sufficient or might we consider `abstract` classes as well?