I released a new meta programming club video a while back on my YouTube channel
But I thought I would write a little about it here too, this is a mirror of the post on my website but I like the community and sharing aspect of posts here on dev.to so here is is :-)
I recently did a little work to flesh out the plugin interface for Myriad. My friend Enrico Sada helped out with
some of the fiddly MsBuild work in dotnet which can be a little confusing at times.
The gist of the plugin is that you must implement the following interface:
type IMyriadGenerator =
abstract member Generate: namespace': string * ast:ParsedInput -> SynModuleOrNamespaceRcd
And annotate you type with the MyriadGeneratorAttribute
specifying the name of your plugin so that it can be found.
Heres an example plugin from the Myriad repo:
[<MyriadGenerator("example1")>]
type Example1Gen() =
interface IMyriadGenerator with
member __.Generate(namespace', _ast) =
let let42 =
SynModuleDecl.CreateLet
[ { SynBindingRcd.Let with
Pattern = SynPatRcd.CreateLongIdent(LongIdentWithDots.CreateString "fourtyTwo", [])
Expr = SynExpr.CreateConst(SynConst.Int32 42) } ]
let componentInfo = SynComponentInfoRcd.Create [ Ident.Create "example1" ]
let nestedModule = SynModuleDecl.CreateNestedModule(componentInfo, [ let42 ])
let namespaceOrModule =
{ SynModuleOrNamespaceRcd.CreateNamespace(Ident.CreateLong namespace')
with Declarations = [ nestedModule ] }
namespaceOrModule
All this example does is generate a simple module like this:
module example1 =
let fourtyTwo = 42
Ast Helping Hand
Unfortunately working with the AST can be quite verbose in Myriad I use FsAst which uses the record update syntax to aid
in the construction of AST nodes by using the record update syntax so you don't have to supply every parameter.
Take a Let binding AST element:
{SynBindingRcd.Let with
Pattern = pattern
Expr = expr }
If we did not use the record update syntax in SynBindingRcd
then we would have to supply every parameter for the let binding:
{
Access = None
Kind = SynBindingKind.NormalBinding
IsInline = false
IsMutable = false
Attributes = SynAttributes.Empty
XmlDoc = PreXmlDoc.Empty
ValData = SynValData(Some MemberFlags.InstanceMember, SynValInfo.Empty, None)
Pattern = pattern
ReturnInfo = None
Expr = expr
Range = range.Zero
Bind = SequencePointInfoForBinding.NoSequencePointAtInvisibleBinding }
Which is not exactly fun, the record update syntax makes these type of things easy to define and compose together.
The new version of Myriad can be found on Nuget here or at its repo.
I hope you enjoyed the video and this brief post!
Until next time!
Top comments (0)