Pergunta
Estou criando uma DSL para um motor de jogo de cartas extensível que estou trabalhando, com boo.
Eu tenho uma macro cartão que cria uma classe para um novo tipo de cartão, e inicializa algumas propriedades no construtor. Essa macro tem algumas submacros para definir outras coisas. Basicamente eu quero que ele vire algo como isto:
card 'A new card':
type TypeA
ability EffectA:
// effect definition
a este:
class ANewCard (Card):
def constructor():
Name = "A new card"
Type = Types.TypeA
AddEffect(EffectA())
class EffectA (Effect):
// effectdefintion
O efeito definitivamente precisa ser uma classe, porque ele vai ser passado em torno de (é um padrão Strategy).
Até agora, eu tenho este esqueleto simples:
macro card:
yield [|
class $(ReferenceExpression(card.Arguments[0])) (Card):
def constructor():
Name = $(card.Arguments[0])
|]
Agora, eu não sei o que devo fazer com card.Body para tornar o código macro add capacidade para o construtor e ao mesmo tempo gerando uma classe aninhada. Alguma ideia? isso pode ser feito com recursos de linguagem atual?
Solução
Pode ser feito. Veja como:
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)()) |]
O crédito vai para Cedric Vivier por me ajudar na boo grupo Google .