Attribute Macro starlark_derive::starlark_module
source · #[starlark_module]
Expand description
Write Starlark modules concisely in Rust syntax.
For example:
#[starlark_module]
fn global(builder: &mut GlobalsBuilder) {
fn cc_binary(name: &str, srcs: Vec<&str>) -> String {
Ok(format!("{:?} {:?}", name, srcs))
}
}
Parameters operate as named parameters of a given type. Each parameter will be unpacked with UnpackValue
, unless:
- It is type
Option
, in which case it will be considered optional. - It is a single argument of type
Arguments
, in which case all arguments will be passed together with minimal interpretation.
There are a number of attributes that can be add to each parameter by writing attributes before the parameter name:
#[starlark(default = "a default")]
- provide a deafult for the parameter if it is omitted.#[starlark(require = pos)]
- require the parameter to be passed by position, not named.#[starlark(require = named)]
- require the parameter to be passed by name, not by position.#[starlark(args)]
- treat the argument as*args
in Starlark, receiving all additional positional arguments as a tuple.#[starlark(kwargs)]
- treat the argument as**kwargs
in Starlark, receiving all additional named arguments as a dictionary.
There are a number of attributes that can be applied to the entire function by writing attributes
before the fn
of the function:
#[starlark(attribute_type = "foo")]
- if the function has.type
applied, return this string. Usually used on constructor functions so thatctor.type
can be used in Starlark code.#[starlark(return_type = "foo")]
- the return type of the function used for documention.#[starlark(speculative_exec_safe)]
- the function is considered safe to execute speculatively: the function should have no global side effects, should not panic, and should finish in reasonable time. The evaluator may invoke such functions early to generate more efficient code.#[starlark(attribute)]
to turn the name into an attribute on the value. Such a function must take exactly one argument, namely a value of the type you have attached it to.
Multiple attributes can be specified either separately #[starlark(require = named)] #[starlark(default = "")]
or
separated with a comman #[starlark(require = named, default = "")]
.
There are two special arguments, distinguished by their type, which provides access to interpreter state:
heap: &'v Heap
gives access to the Starlark heap, for allocating things.eval: &mut Evaluator<'v, '_>
gives access to the Starlark evaluator, which can be used to look at interpreter state.
A module can be used to define globals (with GlobalsBuilder
) or methods on an object (with MethodsBuilder
).
In the case of methods, the first argument to each function will be the object itself, typically named this
.
All these functions interoperate properly with dir()
, getattr()
and hasattr()
.
If a desired function name is also a Rust keyword, use the r#
prefix, e.g. r#type
.
As a more complex example:
#[starlark_module]
fn methods(builder: &mut MethodsBuilder) {
fn r#enum<'v>(
this: Value<'v>,
#[starlark(require = named, default = 3)] index: i32,
heap: &'v Heap,
) -> anyhow::Result<StringValue<'v>> {
Ok(heap.alloc_str(&format!("{this} {index}")))
}
}
This defines a method such that when attached to an object object.enum(index = 12)
will
return the string of the object and the index.