Compare commits

...

4 Commits

Author SHA1 Message Date
Patrick Stevens
95f5ceab03 Add no-attribute support for CreateCatamorphism (#461) 2025-11-28 18:58:27 +00:00
dependabot[bot]
2a7b5822b8 Bump WoofWare.Expect from 0.8.4 to 0.8.5 (#460)
* Bump WoofWare.Expect from 0.8.4 to 0.8.5

---
updated-dependencies:
- dependency-name: WoofWare.Expect
  dependency-version: 0.8.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Deps

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Smaug123 <3138005+Smaug123@users.noreply.github.com>
2025-11-25 11:04:43 +00:00
dependabot[bot]
d344d9a7e9 Bump actions/checkout from 5 to 6 (#459)
Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to 6.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-24 16:36:55 +00:00
patrick-conscriptus[bot]
fab8c0854a Automated commit (#458)
Co-authored-by: patrick-conscriptus[bot] <175414948+patrick-conscriptus[bot]@users.noreply.github.com>
2025-11-23 01:50:13 +00:00
12 changed files with 276 additions and 32 deletions

View File

@@ -25,7 +25,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
with:
fetch-depth: 0 # so that NerdBank.GitVersioning has access to history
- name: Install Nix
@@ -46,7 +46,7 @@ jobs:
security-events: write
steps:
- name: Checkout
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
fetch-depth: 0 # so that NerdBank.GitVersioning has access to history
- name: Install Nix
@@ -65,7 +65,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v5
uses: actions/checkout@v6
- name: Install Nix
uses: cachix/install-nix-action@v31
with:
@@ -80,7 +80,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v5
uses: actions/checkout@v6
- name: Install Nix
uses: cachix/install-nix-action@v31
with:
@@ -93,7 +93,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
fetch-depth: 0 # so that NerdBank.GitVersioning has access to history
- name: Install Nix
@@ -114,7 +114,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v5
uses: actions/checkout@v6
- name: Install Nix
uses: cachix/install-nix-action@v31
with:
@@ -152,7 +152,7 @@ jobs:
nuget-pack:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
with:
fetch-depth: 0 # so that NerdBank.GitVersioning has access to history
- name: Install Nix
@@ -207,7 +207,7 @@ jobs:
runs-on: ubuntu-latest
needs: [nuget-pack]
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
- name: Download NuGet artifact
uses: actions/download-artifact@v6
with:
@@ -287,7 +287,7 @@ jobs:
attestations: write
contents: read
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
- name: Install Nix
uses: cachix/install-nix-action@v31
with:
@@ -325,7 +325,7 @@ jobs:
attestations: write
contents: read
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
- name: Install Nix
uses: cachix/install-nix-action@v31
with:
@@ -366,7 +366,7 @@ jobs:
permissions:
contents: write
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
- name: Download NuGet artifact
uses: actions/download-artifact@v6
with:

View File

@@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@v5
uses: actions/checkout@v6
- name: Install Nix
uses: DeterminateSystems/nix-installer-action@main

View File

@@ -0,0 +1,19 @@
namespace ConsumePluginNoAttr
type ConstNoAttr<'a> =
| Verbatim of 'a
| String of string
type PairOpKindNoAttr =
| NormalSeq
| ThenDoSeq
type TreeNoAttr<'a, 'b> =
| Const of ConstNoAttr<'a> * 'b
| Pair of TreeNoAttr<'a, 'b> * TreeNoAttr<'a, 'b> * PairOpKindNoAttr
| Sequential of TreeNoAttr<'a, 'b> list
| Builder of TreeNoAttr<'a, 'b> * TreeBuilderNoAttr<'b, 'a>
and TreeBuilderNoAttr<'b, 'a> =
| Child of TreeBuilderNoAttr<'b, 'a>
| Parent of TreeNoAttr<'a, 'b>

View File

@@ -77,6 +77,13 @@
<Compile Include="GeneratedCatamorphism.fs">
<MyriadFile>Catamorphism.fs</MyriadFile>
</Compile>
<Compile Include="CatamorphismNoAttribute.fs" />
<Compile Include="GeneratedCatamorphismNoAttribute.fs">
<MyriadFile>CatamorphismNoAttribute.fs</MyriadFile>
<MyriadParams>
<TreeNoAttr>CreateCatamorphism(TreeNoAttrCata)</TreeNoAttr>
</MyriadParams>
</Compile>
<Compile Include="FSharpForFunAndProfitCata.fs" />
<Compile Include="GeneratedFileSystem.fs">
<MyriadFile>FSharpForFunAndProfitCata.fs</MyriadFile>

View File

@@ -0,0 +1,144 @@
//------------------------------------------------------------------------------
// This code was generated by myriad.
// Changes to this file will be lost when the code is regenerated.
//------------------------------------------------------------------------------
namespace ConsumePluginNoAttr
/// Description of how to combine cases during a fold
type TreeBuilderNoAttrCataCase<'b, 'a, 'TreeBuilderNoAttr, 'TreeNoAttr> =
/// How to operate on the Child case
abstract Child : 'TreeBuilderNoAttr -> 'TreeBuilderNoAttr
/// How to operate on the Parent case
abstract Parent : 'TreeNoAttr -> 'TreeBuilderNoAttr
/// Description of how to combine cases during a fold
type TreeNoAttrCataCase<'a, 'b, 'TreeBuilderNoAttr, 'TreeNoAttr> =
/// How to operate on the Const case
abstract Const : ConstNoAttr<'a> -> 'b -> 'TreeNoAttr
/// How to operate on the Pair case
abstract Pair : 'TreeNoAttr -> 'TreeNoAttr -> PairOpKindNoAttr -> 'TreeNoAttr
/// How to operate on the Sequential case
abstract Sequential : 'TreeNoAttr list -> 'TreeNoAttr
/// How to operate on the Builder case
abstract Builder : 'TreeNoAttr -> 'TreeBuilderNoAttr -> 'TreeNoAttr
/// Specifies how to perform a fold (catamorphism) over the type TreeNoAttr and its friends.
type TreeNoAttrCata<'b, 'a, 'TreeBuilderNoAttr, 'TreeNoAttr> =
{
/// How to perform a fold (catamorphism) over the type TreeBuilderNoAttr
TreeBuilderNoAttr : TreeBuilderNoAttrCataCase<'b, 'a, 'TreeBuilderNoAttr, 'TreeNoAttr>
/// How to perform a fold (catamorphism) over the type TreeNoAttr
TreeNoAttr : TreeNoAttrCataCase<'a, 'b, 'TreeBuilderNoAttr, 'TreeNoAttr>
}
/// Methods to perform a catamorphism over the type TreeNoAttr
[<RequireQualifiedAccess>]
module TreeNoAttrCata =
[<RequireQualifiedAccess>]
type private Instruction<'b, 'a> =
| Process__TreeBuilderNoAttr of TreeBuilderNoAttr<'b, 'a>
| Process__TreeNoAttr of TreeNoAttr<'a, 'b>
| TreeBuilderNoAttr_Child
| TreeBuilderNoAttr_Parent
| TreeNoAttr_Pair of PairOpKindNoAttr
| TreeNoAttr_Sequential of int
| TreeNoAttr_Builder
let private loop
(cata : TreeNoAttrCata<'b, 'a, 'TreeBuilderNoAttr, 'TreeNoAttr>)
(instructions : ResizeArray<Instruction<'b, 'a>>)
=
let treeNoAttrStack = ResizeArray<'TreeNoAttr> ()
let treeBuilderNoAttrStack = ResizeArray<'TreeBuilderNoAttr> ()
while instructions.Count > 0 do
let currentInstruction = instructions.[instructions.Count - 1]
instructions.RemoveAt (instructions.Count - 1)
match currentInstruction with
| Instruction.Process__TreeBuilderNoAttr x ->
match x with
| TreeBuilderNoAttr.Child (arg0_0) ->
instructions.Add Instruction.TreeBuilderNoAttr_Child
instructions.Add (Instruction.Process__TreeBuilderNoAttr arg0_0)
| TreeBuilderNoAttr.Parent (arg0_0) ->
instructions.Add Instruction.TreeBuilderNoAttr_Parent
instructions.Add (Instruction.Process__TreeNoAttr arg0_0)
| Instruction.Process__TreeNoAttr x ->
match x with
| TreeNoAttr.Const (arg0_0, arg1_0) -> cata.TreeNoAttr.Const arg0_0 arg1_0 |> treeNoAttrStack.Add
| TreeNoAttr.Pair (arg0_0, arg1_0, arg2_0) ->
instructions.Add (Instruction.TreeNoAttr_Pair (arg2_0))
instructions.Add (Instruction.Process__TreeNoAttr arg0_0)
instructions.Add (Instruction.Process__TreeNoAttr arg1_0)
| TreeNoAttr.Sequential (arg0_0) ->
instructions.Add (Instruction.TreeNoAttr_Sequential ((List.length arg0_0)))
for elt in arg0_0 do
instructions.Add (Instruction.Process__TreeNoAttr elt)
| TreeNoAttr.Builder (arg0_0, arg1_0) ->
instructions.Add Instruction.TreeNoAttr_Builder
instructions.Add (Instruction.Process__TreeNoAttr arg0_0)
instructions.Add (Instruction.Process__TreeBuilderNoAttr arg1_0)
| Instruction.TreeBuilderNoAttr_Child ->
let arg0_0 = treeBuilderNoAttrStack.[treeBuilderNoAttrStack.Count - 1]
treeBuilderNoAttrStack.RemoveAt (treeBuilderNoAttrStack.Count - 1)
cata.TreeBuilderNoAttr.Child arg0_0 |> treeBuilderNoAttrStack.Add
| Instruction.TreeBuilderNoAttr_Parent ->
let arg0_0 = treeNoAttrStack.[treeNoAttrStack.Count - 1]
treeNoAttrStack.RemoveAt (treeNoAttrStack.Count - 1)
cata.TreeBuilderNoAttr.Parent arg0_0 |> treeBuilderNoAttrStack.Add
| Instruction.TreeNoAttr_Pair arg2_0 ->
let arg0_0 = treeNoAttrStack.[treeNoAttrStack.Count - 1]
treeNoAttrStack.RemoveAt (treeNoAttrStack.Count - 1)
let arg1_0 = treeNoAttrStack.[treeNoAttrStack.Count - 1]
treeNoAttrStack.RemoveAt (treeNoAttrStack.Count - 1)
cata.TreeNoAttr.Pair arg0_0 arg1_0 arg2_0 |> treeNoAttrStack.Add
| Instruction.TreeNoAttr_Sequential arg0_0 ->
let arg0_0_len = arg0_0
let arg0_0 =
seq {
for i = treeNoAttrStack.Count - 1 downto treeNoAttrStack.Count - arg0_0 do
yield treeNoAttrStack.[i]
}
|> Seq.toList
treeNoAttrStack.RemoveRange (treeNoAttrStack.Count - arg0_0_len, arg0_0_len)
cata.TreeNoAttr.Sequential arg0_0 |> treeNoAttrStack.Add
| Instruction.TreeNoAttr_Builder ->
let arg0_0 = treeNoAttrStack.[treeNoAttrStack.Count - 1]
treeNoAttrStack.RemoveAt (treeNoAttrStack.Count - 1)
let arg1_0 = treeBuilderNoAttrStack.[treeBuilderNoAttrStack.Count - 1]
treeBuilderNoAttrStack.RemoveAt (treeBuilderNoAttrStack.Count - 1)
cata.TreeNoAttr.Builder arg0_0 arg1_0 |> treeNoAttrStack.Add
treeBuilderNoAttrStack, treeNoAttrStack
/// Execute the catamorphism.
let runTreeBuilderNoAttr
(cata : TreeNoAttrCata<'b, 'a, 'TreeBuilderNoAttrRet, 'TreeNoAttrRet>)
(x : TreeBuilderNoAttr<'b, 'a>)
: 'TreeBuilderNoAttrRet
=
let instructions = ResizeArray ()
instructions.Add (Instruction.Process__TreeBuilderNoAttr x)
let treeBuilderNoAttrRetStack, treeNoAttrRetStack = loop cata instructions
Seq.exactlyOne treeBuilderNoAttrRetStack
/// Execute the catamorphism.
let runTreeNoAttr
(cata : TreeNoAttrCata<'b, 'a, 'TreeBuilderNoAttrRet, 'TreeNoAttrRet>)
(x : TreeNoAttr<'a, 'b>)
: 'TreeNoAttrRet
=
let instructions = ResizeArray ()
instructions.Add (Instruction.Process__TreeNoAttr x)
let treeBuilderNoAttrRetStack, treeNoAttrRetStack = loop cata instructions
Seq.exactlyOne treeNoAttrRetStack

View File

@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>

View File

@@ -0,0 +1,51 @@
namespace WoofWare.Myriad.Plugins.Test
open System.Threading
open NUnit.Framework
open FsUnitTyped
open ConsumePluginNoAttr
open FsCheck
[<TestFixture>]
module TestCataGeneratorNoAttr =
let idCata<'a, 'b> : TreeNoAttrCata<'a, 'b, _, _> =
{
TreeNoAttr =
{ new TreeNoAttrCataCase<_, _, _, _> with
member _.Const x y = Const (x, y)
member _.Pair x y z = Pair (x, y, z)
member _.Sequential xs = Sequential xs
member _.Builder x b = Builder (x, b)
}
TreeBuilderNoAttr =
{ new TreeBuilderNoAttrCataCase<_, _, _, _> with
member _.Child x = Child x
member _.Parent x = Parent x
}
}
[<Test>]
let ``Example`` () =
let x =
TreeNoAttr.Pair (
TreeNoAttr.Const (ConstNoAttr.Verbatim 0, "hi"),
TreeNoAttr.Const (ConstNoAttr.String "", "bye"),
PairOpKindNoAttr.ThenDoSeq
)
TreeNoAttrCata.runTreeNoAttr idCata x |> shouldEqual x
[<Test>]
let ``Cata works`` () =
let builderCases = ref 0
let property (x : TreeNoAttr<int, string>) =
match x with
| TreeNoAttr.Builder _ -> Interlocked.Increment builderCases |> ignore
| _ -> ()
TreeNoAttrCata.runTreeNoAttr idCata x = x
Check.QuickThrowOnFailure property
builderCases.Value |> shouldBeGreaterThan 10

View File

@@ -32,6 +32,7 @@
<Compile Include="TestCapturingMockGenerator\TestCapturingMockGeneratorNoAttr.fs" />
<Compile Include="TestJsonSerialize\TestJsonSerde.fs" />
<Compile Include="TestCataGenerator\TestCataGenerator.fs" />
<Compile Include="TestCataGenerator\TestCataGeneratorNoAttr.fs" />
<Compile Include="TestCataGenerator\TestDirectory.fs" />
<Compile Include="TestCataGenerator\TestGift.fs" />
<Compile Include="TestCataGenerator\TestMyList.fs" />
@@ -61,7 +62,7 @@
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
<PackageReference Include="NUnit" Version="4.3.2" />
<PackageReference Include="NUnit3TestAdapter" Version="5.2.0" />
<PackageReference Include="WoofWare.Expect" Version="0.8.4" />
<PackageReference Include="WoofWare.Expect" Version="0.8.5" />
</ItemGroup>
<ItemGroup>

View File

@@ -1209,6 +1209,10 @@ type CreateCatamorphismGenerator () =
member _.ValidInputExtensions = [ ".fs" ]
member _.Generate (context : GeneratorContext) =
let targetedTypes =
MyriadParamParser.render context.AdditionalParameters
|> Map.map (fun _ v -> v.Split '!' |> Array.toList |> List.map DesiredGenerator.Parse)
let ast, _ =
Ast.fromFilename context.InputFilename |> Async.RunSynchronously |> Array.head
@@ -1218,17 +1222,26 @@ type CreateCatamorphismGenerator () =
let namespaceAndTypes =
types
|> List.choose (fun (ns, types) ->
let typeWithAttr =
types
|> List.tryPick (fun ty ->
match SynTypeDefn.getAttribute typeof<CreateCatamorphismAttribute>.Name ty with
| None -> None
| Some attr -> Some (attr.ArgExpr, ty)
)
|> List.collect (fun (ns, types) ->
types
|> List.choose (fun typeDef ->
match SynTypeDefn.getAttribute typeof<CreateCatamorphismAttribute>.Name typeDef with
| None ->
let name = SynTypeDefn.getName typeDef |> List.map _.idText |> String.concat "."
match typeWithAttr with
| Some taggedType ->
match Map.tryFind name targetedTypes with
| Some desired ->
desired
|> List.tryPick (fun generator ->
match generator with
| DesiredGenerator.CreateCatamorphism cataOutputName ->
Some (SynExpr.CreateConst cataOutputName, typeDef)
| _ -> None
)
| None -> None
| Some attr -> Some (attr.ArgExpr, typeDef)
)
|> List.map (fun (typeName, taggedType) ->
let unions, records, others =
(([], [], []), types)
||> List.fold (fun
@@ -1246,8 +1259,8 @@ type CreateCatamorphismGenerator () =
failwith
$"Error: all types recursively defined together with a CreateCatamorphism type must be discriminated unions or records. %+A{others}"
Some (ns, taggedType, unions, records)
| _ -> None
(ns, (typeName, taggedType), unions, records)
)
)
let modules =

View File

@@ -1,11 +1,14 @@
namespace WoofWare.Myriad.Plugins
open System
type internal DesiredGenerator =
| InterfaceMock of isInternal : bool option
| CapturingInterfaceMock of isInternal : bool option
| JsonParse of extensionMethod : bool option
| JsonSerialize of extensionMethod : bool option
| HttpClient of extensionMethod : bool option
| CreateCatamorphism of typeName : string
static member Parse (s : string) =
match s with
@@ -24,4 +27,10 @@ type internal DesiredGenerator =
| "HttpClient" -> DesiredGenerator.HttpClient None
| "HttpClient(true)" -> DesiredGenerator.HttpClient (Some true)
| "HttpClient(false)" -> DesiredGenerator.HttpClient (Some false)
| _ -> failwith $"Failed to parse as a generator specification: %s{s}"
| _ ->
let prefix = "CreateCatamorphism("
if s.StartsWith (prefix, StringComparison.Ordinal) && s.EndsWith ')' then
DesiredGenerator.CreateCatamorphism (s.Substring (prefix.Length, s.Length - prefix.Length - 1))
else
failwith $"Failed to parse as a generator specification: %s{s}"

6
flake.lock generated
View File

@@ -20,11 +20,11 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1763191728,
"narHash": "sha256-esRhOS0APE6k40Hs/jjReXg+rx+J5LkWw7cuWFKlwYA=",
"lastModified": 1764138170,
"narHash": "sha256-2bCmfCUZyi2yj9FFXYKwsDiaZmizN75cLhI/eWmf3tk=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "1d4c88323ac36805d09657d13a5273aea1b34f0c",
"rev": "bb813de6d2241bcb1b5af2d3059f560c66329967",
"type": "github"
},
"original": {

View File

@@ -386,8 +386,8 @@
},
{
"pname": "WoofWare.Expect",
"version": "0.8.4",
"hash": "sha256-UI7f2nt4g4Gg1Ke/IChrA4fpVOYAChXpvR6zkKfkmzE="
"version": "0.8.5",
"hash": "sha256-rMlkk1osadQYwxmb0KAHqsB51hinTf7NzI0zyovpx04="
},
{
"pname": "WoofWare.NUnitTestRunner",