Records
The input file in this example Library.fs
looks like this:
namespace Example
open Myriad.Plugins
[<Generator.Fields "fields">]
type Test1 = { one: int; two: string; three: float; four: float32 }
type Test2 = { one: Test1; two: string }
An attribute is used by the fields plugin so that the code generator knows which parts of the input AST should be consumed by the plugin. If you had several records and you only wanted the fields plugin to operate on Test1
then the attribute would be used like in the example about to only apply Generator.Fields
to the Test1
record. Note, if you wanted a plugin that just processes the whole input then there is no need to provide such an attribute. Myriad aims to be a library rather than a full framework that ties you to the mechanism used to input and generate code, its up to you how you generate the code, Myriad just aims to help to make this as painless and flexible as possible.
To control what namespace is used as well as supplying any other information to plugins a myriad.toml
configuration file is used. This is specified in the generator attribute, in the example above you can see the configuration section is fields
[<Generator.Fields "fields">]
. The corresponding myriad.toml
file looks as follows:
[fields]
namespace = "TestFields"
The fields plugin uses only a single configuration key namespace
to control the resulting namespace the record helpers are generated
The fields plugin in this example will generate the following code at prebuild and compile the code into your assembly:
//------------------------------------------------------------------------------
// This code was generated by myriad.
// Changes to this file will be lost when the code is regenerated.
//------------------------------------------------------------------------------
namespace rec TestFields
module Test1 =
open Example
let one (x : Test1) = x.one
let two (x : Test1) = x.two
let three (x : Test1) = x.three
let four (x : Test1) = x.four
let create (one : Test1) (two : string) (three : float) (four : float32) : Test1 =
{ one = one
two = two
three = three
four = four }
let map (mapone : int -> int) (maptwo : string -> string) (mapthree : float -> float) (mapfour : float32 -> float32) (record': Test1) =
{ record' with
one = mapone record'.one
two = maptwo record'.two
three = mapthree record'.three
four = mapfour record'.four }
The fields plugin generates a map
for each field in the input record, a create
function taking each field, and a map
function that takes one function per field in the input record.
The map functions for each field are useful in situations where you just want to use a single field from a record in a lambda like a list of records:
let records = [{one = "a"; two = "aa"; three = 42.0; four = 172.0f}
{one = "b"; two = "bb"; three = 42.0; four = 172.0f}]
records |> List.sortBy Test1.one