Pregunta
Estoy creando una conexión DSL para un motor de juego de cartas extensible que estoy trabajando, con Boo.
Tengo una macro tarjeta que crea una clase para un nuevo tipo de tarjeta, e inicializa algunas propiedades en el constructor. Macro que tiene unos submacros para configurar otras cosas. Básicamente quiero que se convierta algo como esto:
card 'A new card':
type TypeA
ability EffectA:
// effect definition
en esto:
class ANewCard (Card):
def constructor():
Name = "A new card"
Type = Types.TypeA
AddEffect(EffectA())
class EffectA (Effect):
// effectdefintion
El efecto definitivamente tiene que ser una clase, ya que se pasa alrededor (que es un patrón de estrategia).
Hasta el momento, no tengo este simple esqueleto:
macro card:
yield [|
class $(ReferenceExpression(card.Arguments[0])) (Card):
def constructor():
Name = $(card.Arguments[0])
|]
Ahora, yo no sé lo que debo hacer con card.Body para hacer la macro capacidad de añadir código al constructor y al mismo tiempo generar una clase anidada. ¿Alguna idea? ¿Es posible hacerlo con capacidades de idioma actual?
Solución
Se puede hacer. He aquí cómo:
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)()) |]
El crédito va a Cedric Vivier por ayudarme en el Boo grupo Google .