DEV Community

Dave Thomas
Dave Thomas

Posted on

An Introduction to Myriad

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

All this example does is generate a simple module like this:

module example1 =
    let fourtyTwo = 42
Enter fullscreen mode Exit fullscreen mode

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 }
Enter fullscreen mode Exit fullscreen mode

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 }
Enter fullscreen mode Exit fullscreen mode

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)