fn render_fun()

in starlark_derive/src/render.rs [119:234]


fn render_fun(x: StarFun) -> TokenStream {
    let span = x.span();

    let name_str = ident_string(&x.name);
    let signature = render_signature(&x);
    let documentation = render_documentation(&x);
    let binding = render_binding(&x);
    let is_method = x.is_method();

    let StarFun {
        name,
        type_attribute,
        attrs,
        args: _,
        return_type,
        return_type_arg: _,
        speculative_exec_safe,
        body,
        source: _,
        docstring: _,
    } = x;

    let typ = match type_attribute {
        Some(x) => quote_spanned! {
            span=>
            std::option::Option::Some({
                const TYPE_N: usize = #x.len();
                static TYPE: starlark::values::StarlarkStrNRepr<TYPE_N> =
                    starlark::values::StarlarkStrNRepr::new(#x);
                TYPE.unpack()
            })
        },
        None => {
            quote_spanned! {
                span=>
                std::option::Option::None
            }
        }
    };

    let signature_arg = signature.as_ref().map(
        |_| quote_spanned! {span=> __signature: &starlark::eval::ParametersSpec<starlark::values::FrozenValue>,},
    );
    let signature_val = signature
        .as_ref()
        .map(|_| quote_spanned! {span=> __signature});
    let signature_val_ref = signature
        .as_ref()
        .map(|_| quote_spanned! {span=> &__signature});

    let (this_param, this_arg, builder_set) = if is_method {
        (
            quote_spanned! {span=> __this: starlark::values::Value<'v>, },
            quote_spanned! {span=> __this, },
            quote_spanned! {span=>
                #[allow(clippy::redundant_closure)]
                globals_builder.set_method(
                    #name_str,
                    #speculative_exec_safe,
                    __documentation_renderer,
                    #typ,
                    move |eval, __this, parameters| {#name(eval, __this, parameters, #signature_val_ref)},
                );
            },
        )
    } else {
        (
            quote_spanned! {span=> },
            quote_spanned! {span=> },
            quote_spanned! {span=>
                #[allow(clippy::redundant_closure)]
                globals_builder.set_function(
                    #name_str,
                    #speculative_exec_safe,
                    __documentation_renderer,
                    #typ,
                    move |eval, parameters| {#name(eval, parameters, #signature_val_ref)},
                );
            },
        )
    };

    quote_spanned! {
        span=>
        #( #attrs )*
        #[allow(non_snake_case)] // Starlark doesn't have this convention
        fn #name<'v>(
            eval: &mut starlark::eval::Evaluator<'v, '_>,
            #this_param
            parameters: &starlark::eval::Arguments<'v, '_>,
            #signature_arg
        ) -> anyhow::Result<starlark::values::Value<'v>> {
            fn inner<'v>(
                #[allow(unused_variables)]
                eval: &mut starlark::eval::Evaluator<'v, '_>,
                #this_param
                __args: &starlark::eval::Arguments<'v, '_>,
                #signature_arg
            ) -> #return_type {
                #[allow(unused_variables)]
                let heap = eval.heap();
                #binding
                #body
            }
            match inner(eval, #this_arg parameters, #signature_val) {
                Ok(v) => Ok(eval.heap().alloc(v)),
                Err(e) => Err(e),
            }
        }
        {
            #signature
            #documentation
            #builder_set
        }
    }
}