Domanda
Sto creando un DSL per un motore estensibile gioco di carte su cui sto lavorando, con il fischio.
Ho una macro carta che crea una classe per un nuovo tipo di carta, e inizializza alcune proprietà nel costruttore. Questo macro ha un paio di submacros per l'impostazione altre cose. Fondamentalmente voglio che diventi qualcosa di simile:
card 'A new card':
type TypeA
ability EffectA:
// effect definition
in questo modo:
class ANewCard (Card):
def constructor():
Name = "A new card"
Type = Types.TypeA
AddEffect(EffectA())
class EffectA (Effect):
// effectdefintion
L'effetto sicuramente bisogno di essere una classe, perché sarà passato in giro (si tratta di un modello di strategia).
Finora, ho questo semplice scheletro:
macro card:
yield [|
class $(ReferenceExpression(card.Arguments[0])) (Card):
def constructor():
Name = $(card.Arguments[0])
|]
Ora, io non so che cosa devo fare con card.Body per rendere la macro capacità aggiungere codice al costruttore, mentre anche generare una classe annidata. qualche idea? Questo può essere fatto con capacità linguistiche attuali?
Soluzione
Si può fare. Ecco come:
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)()) |]
Il credito va a Cedric Vivier per avermi aiutato nel boo gruppo Google .