Search code examples
macrosboo

Difficult boo syntactic macro


I'm creating a DSL for an extensible card game engine I'm working on, with boo.

I have a card macro that creates a class for a new type of card, and initializes some properties in the constructor. That macro has a few submacros for setting other things. Basically I want it to turn something like this:

card 'A new card':
    type TypeA
    ability EffectA:
        // effect definition

into this:

class ANewCard (Card):
    def constructor():
        Name = "A new card"
        Type = Types.TypeA
        AddEffect(EffectA())

    class EffectA (Effect):
        // effectdefintion

The effect definitely needs to be a class, because it will be passed around (it's a Strategy pattern).

So far, I have this simple skeleton:

macro card:
    yield [|
        class $(ReferenceExpression(card.Arguments[0])) (Card):
            def constructor():
                Name = $(card.Arguments[0])
    |]

Now, I don't know what should I do with card.Body to make the ability macro add code to the constructor while also generating a nested class. Any thoughts? Can this be done with current language capabilities?


Solution

  • It can be done. Here's how:

    import Boo.Lang.Compiler.Ast 
    import Boo.Lang.PatternMatching 
    
    macro card(name as string): 
        klass = [| 
            class $(ReferenceExpression(name)): 
                def constructor(): 
                    Name = $name
        |] 
        klass.Members.Add(card["effect"]) 
        klass.GetConstructor(0).Body.Add(card["effect-ctor"] as Expression) 
        yield klass 
    
    macro effect(eff as ReferenceExpression): 
        card["effect"] = [| 
            class $eff (Effect): 
                pass 
        |] 
        card["effect-ctor"] = [| Effects.Add($(eff)()) |] 
    

    Credit goes to Cedric Vivier for helping me out in the boo Google group.