///|
/// A generator that takes arguments: `#demo.getters` on a struct gives every
/// field a getter, and `skip=` names the fields that get none.
struct Getters {}
///|
impl @gen.Generator for Getters with fn name(_) {
"getters"
}
///|
impl @gen.Generator for Getters with fn generate(_, decls) {
let out = []
for decl in decls {
guard decl is Struct(name~, fields~, attrs~, ..) else { continue }
guard @attr.find(attrs, "demo.getters") is Some(annotation) else {
continue
}
let skip = @attr.Spec::new("demo.getters")
.many("skip", Ident)
.bind(annotation)
.strs("skip")
for field in fields {
guard !skip.contains(field.name) else { continue }
let source =
#|fn $T::$field(self : $T) -> $Ty {
#| self.$field
#|}
out.push(
@quote.items(source)
.set("T", @quote.ident(name))
.set("field", @quote.ident(field.name))
.set("Ty", @quote.ty(field.ty).render())
.render(),
)
}
}
@quote.join(out)
}
///|
/// With no arguments it reads the bundled declarations, so the example runs as is.
async fn main {
let args = @env.args()[1:]
let args = if args.is_empty() {
["src/examples/getters/models.txt", "-o", "_build/getters.g.mbt"][:]
} else {
args
}
@cli.run(Getters::{ }, args)
}